diff --git a/CHANGELOG.md b/CHANGELOG.md index 425e9c023..8bd90feb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,46 @@ incremental in minor, bugfixes only are patches. See [0Ver](https://0ver.org/). +## 0.15.0 WIP + +### Features + +- Adds Higher Kinded Types partial support +- **Breaking**: makes our `mypy` plugin not optional, but required! +- **Breaking**: changes all `RequiresContext`-based type arguments order, + previously we used to specify `_EnvType` as the first type argument, + now it is the last one. This is done to respect new HKT rules +- **Breaking**: removes all old interfaces from `primitives/interfaces.py`, + use new typeclasses instead +- **Breaking**: removes `value_or` pointfree method, + because it is impossible to express with HKT +- **Breaking**: removes `.value_or`, `.unwrap`, and `.failure` methods + from `FutureResult` and `RequiresContext` based types, + because we do require these methods to raise an exception on failure, + but these methods were lazy and did not raise the required exception +- **Breaking**: changes how `is_successful` is typed: + now we allow any `Unwrappable` interface instances there, + including custom ones +- **Breaking**: changes `UnwrapFailedError` constructor, + now it does accept an `Unwrappable` instance instead of a `BaseContainer` +- Adds new public interfaces: see `returns.interfaces` +- Adds `methods` package with all the composition methods we support +- Adds `collect_trace` helper function for better development experience +- Adds missing `from_requires_context_future_result` to `RequiresContext` +- Adds `@abstractmethod` to abstract methods in abstract containers + like `Result`, `Maybe`, and `IOResult` +- Adds `__slots__` to `UnwrapFailedError` with `halted_container` + +### Bugfixes + +- **Breaking**: fixes serious typing issue and changes how `flow` works, + now it has a hard limit of 21 parameters: 1 instance + 20 functions + +### Misc + +- Adds a lot of new typetests + + ## 0.14.0 ### Features diff --git a/README.md b/README.md index b0ac8ecfb..8c5d36ece 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ Make your functions return something meaningful, typed, and safe! pip install returns ``` -You might also want to [configure](https://returns.readthedocs.io/en/latest/pages/container.html#type-safety) +You are also required to [configure](https://returns.readthedocs.io/en/latest/pages/container.html#type-safety) `mypy` correctly and install our plugin to fix [this existing issue](https://github.com/python/mypy/issues/3157): @@ -123,7 +123,7 @@ Much better, isn't it? ## RequiresContext container -Many developers do use some kind of [dependency injection](https://github.com/dry-python/dependencies) in Python. +Many developers do use some kind of dependency injection in Python. And usually it is based on the idea that there's some kind of a container and assembly process. @@ -193,11 +193,11 @@ from returns.context import RequiresContext class _Deps(Protocol): # we rely on abstractions, not direct values or types WORD_THRESHOLD: int -def calculate_points(word: str) -> RequiresContext[_Deps, int]: +def calculate_points(word: str) -> RequiresContext[int, _Deps]: guessed_letters_count = len([letter for letter in word if letter != '.']) return _award_points_for_letters(guessed_letters_count) -def _award_points_for_letters(guessed: int) -> RequiresContext[_Deps, int]: +def _award_points_for_letters(guessed: int) -> RequiresContext[int, _Deps]: return RequiresContext( lambda deps: 0 if guessed < deps.WORD_THRESHOLD else guessed, ) @@ -208,7 +208,7 @@ And have the type-safety to check what you pass to cover your back. Check out [RequiresContext](https://returns.readthedocs.io/en/latest/pages/context.html) docs for more. There you will learn how to make `'.'` also configurable. We also have [RequiresContextResult](https://returns.readthedocs.io/en/latest/pages/context.html#requirescontextresult-container) -for context-related operations that might fail. +for context-related operations that might fail. And also [RequiresContextIOResult](https://returns.readthedocs.io/en/latest/pages/context.html#requirescontextioresult-container) and [RequiresContextFutureResult](https://returns.readthedocs.io/en/latest/pages/context.html#requirescontextfutureresult-container). ## Result container diff --git a/docs/index.rst b/docs/index.rst index e4e9ceb80..7ee6e7dae 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -18,6 +18,8 @@ Contents pages/container.rst pages/railway.rst + pages/hkt.rst + pages/interfaces.rst .. toctree:: :maxdepth: 2 @@ -35,6 +37,7 @@ Contents pages/pipeline.rst pages/converters.rst + pages/methods.rst pages/pointfree.rst pages/functions.rst pages/curry.rst diff --git a/docs/pages/container.rst b/docs/pages/container.rst index 7bef7ea6d..a7622f319 100644 --- a/docs/pages/container.rst +++ b/docs/pages/container.rst @@ -69,7 +69,7 @@ The difference is simple: - ``map`` works with functions that return regular value - ``bind`` works with functions that return new container of the same type -:func:`~returns.primitives.container.Bindable.bind` +:func:`returns.primitives.container.Bindable.bind` is used to literally bind two different containers together. .. code:: python @@ -83,7 +83,7 @@ is used to literally bind two different containers together. # Can be assumed as either Success[float] or Failure[str]: result: Result[float, str] = value.bind(may_fail) -And we have :func:`~returns.primitives.container.Mappable.map` +And we have :func:`returns.interfaces.mappable.Mappable.map` to use containers with regular functions. .. code:: python @@ -335,11 +335,3 @@ It defines some basic things like representation, hashing, pickling, etc. .. automodule:: returns.primitives.container :members: :special-members: - -Here are our interfaces (or protocols to be more specific) -that we use inside our app: - -.. autoclasstree:: returns.primitives.interfaces - -.. automodule:: returns.primitives.interfaces - :members: diff --git a/docs/pages/context.rst b/docs/pages/context.rst index 0e11f9dbd..bb7ab6cd5 100644 --- a/docs/pages/context.rst +++ b/docs/pages/context.rst @@ -1,7 +1,7 @@ Context ======= -`Dependency injection `_ is a popular software architechture pattern. +Dependency injection is a popular software architechture pattern. It's main idea is that you provide `Inversion of Control `_ and can pass different things into your logic instead of hardcoding you stuff. @@ -125,11 +125,11 @@ Let's see how our code changes: class _Deps(Protocol): # we rely on abstractions, not direct values or types WORD_THRESHOLD: int - def calculate_points(word: str) -> RequiresContext[_Deps, int]: + def calculate_points(word: str) -> RequiresContext[int, _Deps]: guessed_letters_count = len([letter for letter in word if letter != '.']) return _award_points_for_letters(guessed_letters_count) - def _award_points_for_letters(guessed: int) -> RequiresContext[_Deps, int]: + def _award_points_for_letters(guessed: int) -> RequiresContext[int, _Deps]: return RequiresContext( lambda deps: 0 if guessed < deps.WORD_THRESHOLD else guessed, ) @@ -149,7 +149,7 @@ How can we do that with our existing function? .. code:: python - def calculate_points(word: str) -> RequiresContext[_Deps, int]: + def calculate_points(word: str) -> RequiresContext[int, _Deps]: guessed_letters_count = len([letter for letter in word if letter != '.']) return _award_points_for_letters(guessed_letters_count) @@ -173,8 +173,8 @@ Let's see the final result: WORD_THRESHOLD: int UNGUESSED_CHAR: str - def calculate_points(word: str) -> RequiresContext[_Deps, int]: - def factory(deps: _Deps) -> RequiresContext[_Deps, int]: + def calculate_points(word: str) -> RequiresContext[int, _Deps]: + def factory(deps: _Deps) -> RequiresContext[int, _Deps]: guessed_letters_count = len([ letter for letter in word if letter != deps.UNGUESSED_CHAR ]) @@ -203,7 +203,7 @@ It can be illustrated as a simple nested function: ... def inner(deps: str) -> bool: ... return len(deps) > limit ... return inner - ... + >>> assert first(2)('abc') # first(limit)(deps) >>> assert not first(5)('abc') # first(limit)(deps) @@ -225,7 +225,7 @@ We can wrap it in ``RequiresContext`` container to allow better composition! >>> from returns.context import RequiresContext - >>> def first(limit: int) -> RequiresContext[str, bool]: + >>> def first(limit: int) -> RequiresContext[bool, str]: ... def inner(deps: str) -> bool: ... return len(deps) > limit ... return RequiresContext(inner) # wrapping function here! @@ -252,7 +252,7 @@ And then normal logical execution happens. RequiresContextResult container ------------------------------- -This container is a combintaion of ``RequiresContext[env, Result[a, b]]``. +This container is a combintaion of ``RequiresContext[Result[a, b], env]``. Which means that it is a wrapper around pure function that might fail. We also added a lot of useful methods for this container, @@ -272,7 +272,7 @@ Use it when you work with pure context-related functions that might fail. RequiresContextIOResult container --------------------------------- -This container is a combintaion of ``RequiresContext[env, IOResult[a, b]]``. +This container is a combintaion of ``RequiresContext[IOResult[a, b], env]``. Which means that it is a wrapper around impure function that might fail. We also added a lot of useful methods for this container, @@ -301,7 +301,7 @@ This is basically **the main type** that is going to be used in most apps. RequiresContextFutureResult container ------------------------------------- -This container is a combintaion of ``RequiresContext[env, FutureResult[a, b]]``. +This container is a combintaion of ``RequiresContext[FutureResult[a, b], env]``. Which means that it is a wrapper around impure async function that might fail. Here's how it should be used: @@ -334,7 +334,7 @@ Here's how it should be used: def _fetch_post( post_id: int, - ) -> RequiresContextFutureResultE[httpx.AsyncClient, _Post]: + ) -> RequiresContextFutureResultE[_Post, httpx.AsyncClient]: return ContextFutureResult[httpx.AsyncClient].ask().bind_future_result( lambda client: future_safe(client.get)(_URL.format(post_id)), ).bind_result( @@ -345,7 +345,7 @@ Here's how it should be used: def show_titles( number_of_posts: int, - ) -> RequiresContextFutureResultE[httpx.AsyncClient, Sequence[_TitleOnly]]: + ) -> RequiresContextFutureResultE[Sequence[_TitleOnly], httpx.AsyncClient]: return RequiresContextFutureResultE.from_iterable([ # Notice how easily we compose async and sync functions: _fetch_post(post_id).map(lambda post: post['title']) @@ -549,7 +549,7 @@ We can model the similar idea with ``RequiresContext``: >>> from returns.context import RequiresContext - >>> def my_function(first: int, second: int) -> RequiresContext[bool, int]: + >>> def my_function(first: int, second: int) -> RequiresContext[int, bool]: ... def factory(print_result: bool) -> int: ... original = first + second ... if print_result: @@ -566,21 +566,21 @@ it is easier to change the behaviour of a function with ``RequiresContext``. While decorator with arguments glues values to a function forever. Decide when you need which behaviour carefully. -Why can’t we use RequiresContext[e, Result] instead of RequiresContextResult? +Why can’t we use RequiresContext[Result, e] instead of RequiresContextResult? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ We actually can! But, it is harder to write. And ``RequiresContextResult`` is actually -the very same thing as ``RequiresContext[e, Result]``, but has nicer API: +the very same thing as ``RequiresContext[Result, e]``, but has nicer API: .. code:: python - x: RequiresContext[int, Result[int, str]] + x: RequiresContext[Result[int, str], int] x.map(lambda result: result.map(lambda number: number + 1)) # Is the same as: - y: RequiresContextResult[int, int, str] + y: RequiresContextResult[int, str, int] y.map(lambda number: number + 1) The second one looks better, doesn't it? @@ -599,8 +599,8 @@ So, using this technique is better: from returns.context import Context, RequiresContext - def some_context(*args, **kwargs) -> RequiresContext[int, str]: - def factory(deps: int) -> RequiresContext[int, str]: + def some_context(*args, **kwargs) -> RequiresContext[str, int]: + def factory(deps: int) -> RequiresContext[str, int]: ... return Context[int].ask().bind(factory) @@ -615,7 +615,7 @@ that do pretty much the same as ``RequiresContext`` container. What is the difference? Why do we need each of them? Let's find out! -Tools like `dependencies `_ +Tools like `dependencies `_ or `punq `_ tries to: @@ -635,7 +635,7 @@ All it does is: provides simple API to compose functions that need additional context (or dependencies) to run. You can even use them together: ``RequiresContext`` will pass depedencies -built by ``dry-python/dependencies`` (or any other tool of your choice) +built by ``punq`` (or any other tool of your choice) as a ``deps`` parameter to ``RequiresContext`` instance. When to use which? Let's dig into it! diff --git a/docs/pages/contrib/mypy_plugins.rst b/docs/pages/contrib/mypy_plugins.rst index 80775ac35..607123694 100644 --- a/docs/pages/contrib/mypy_plugins.rst +++ b/docs/pages/contrib/mypy_plugins.rst @@ -49,13 +49,15 @@ This will allow to keep them in sync with the upstream. Supported features ------------------ +- ``kind`` feature adds Higher Kinded Types (HKT) support - ``curry`` feature allows to write typed curried functions - ``partial`` feature allows to write typed partial application - ``flow`` feature allows to write better typed functional pipelines + with ``flow`` function +- ``pipe`` feature allows to write better typed functional pipelines + with ``pipe`` function - ``decorators`` allows to infer types of functions that are decorated with ``@safe``, ``@maybe``, ``@impure``, etc -- ``pointfree`` provides better typing inference - for some problematic :ref:`pointfree` helpers Further reading @@ -71,11 +73,22 @@ API Reference Plugin defenition ~~~~~~~~~~~~~~~~~ +.. automodule:: returns.contrib.mypy._consts + :members: + .. autoclasstree:: returns.contrib.mypy.returns_plugin .. automodule:: returns.contrib.mypy.returns_plugin :members: +Kind +~~~~ + +.. autoclasstree:: returns.contrib.mypy._features.kind + +.. automodule:: returns.contrib.mypy._features.kind + :members: + Curry ~~~~~ @@ -100,19 +113,18 @@ Flow .. automodule:: returns.contrib.mypy._features.flow :members: -Decorators -~~~~~~~~~~ +Pipe +~~~~ -.. autoclasstree:: returns.contrib.mypy._features.decorators +.. autoclasstree:: returns.contrib.mypy._features.pipe -.. automodule:: returns.contrib.mypy._features.decorators +.. automodule:: returns.contrib.mypy._features.pipe :members: +Decorators +~~~~~~~~~~ -Pointfree -~~~~~~~~~ - -.. autoclasstree:: returns.contrib.mypy._features.pointfree +.. autoclasstree:: returns.contrib.mypy._features.decorators -.. automodule:: returns.contrib.mypy._features.pointfree +.. automodule:: returns.contrib.mypy._features.decorators :members: diff --git a/docs/pages/hkt.rst b/docs/pages/hkt.rst new file mode 100644 index 000000000..6c7c746a7 --- /dev/null +++ b/docs/pages/hkt.rst @@ -0,0 +1,10 @@ +.. _hkt: + +Higher Kinded Types +=================== + +API Reference +------------- + +.. automodule:: returns.primitives.hkt + :members: diff --git a/docs/pages/interfaces.rst b/docs/pages/interfaces.rst new file mode 100644 index 000000000..54fa6faa6 --- /dev/null +++ b/docs/pages/interfaces.rst @@ -0,0 +1,16 @@ +.. _interfaces: + +Interfaces +========== + +API Reference +------------- + +.. automodule:: returns.interfaces.mappable + :members: + +.. automodule:: returns.interfaces.bindable + :members: + +.. automodule:: returns.interfaces.applicative + :members: diff --git a/docs/pages/methods.rst b/docs/pages/methods.rst new file mode 100644 index 000000000..d97fba179 --- /dev/null +++ b/docs/pages/methods.rst @@ -0,0 +1,17 @@ +.. _methods: + +Methods +======= + + +API Reference +------------- + +.. autofunction:: returns.methods.bind.internal_bind +.. autofunction:: returns.methods.bind.bind + +.. autofunction:: returns.methods.map.internal_map +.. autofunction:: returns.methods.map.map_ + +.. autofunction:: returns.methods.apply.internal_apply +.. autofunction:: returns.methods.apply diff --git a/docs/pages/pointfree.rst b/docs/pages/pointfree.rst index e5f813099..01c06624f 100644 --- a/docs/pages/pointfree.rst +++ b/docs/pages/pointfree.rst @@ -205,23 +205,6 @@ Or with function as the first parameter: ... ) == Some(5) -value_or --------- - -Allows to unwrap values from containers: - -.. code:: python - - >>> from returns.pointfree import value_or - >>> from returns.result import Result - >>> from returns.pipeline import flow - - >>> assert flow(Result.from_value(1), value_or(2)) == 1 - >>> assert flow(Result.from_failure(1), value_or(2)) == 2 - -All containers with ``.value_or`` method are supported. - - Further reading --------------- @@ -265,5 +248,3 @@ API Reference .. autofunction:: returns.pointfree.rescue .. autofunction:: returns.pointfree.apply - -.. autofunction:: returns.pointfree.value_or diff --git a/poetry.lock b/poetry.lock index f4447da83..b4000e28f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -96,7 +96,7 @@ description = "Python package for providing Mozilla's CA Bundle." name = "certifi" optional = false python-versions = "*" -version = "2020.4.5.1" +version = "2020.6.20" [[package]] category = "dev" @@ -129,7 +129,7 @@ version = "7.1.2" [[package]] category = "dev" description = "Cross-platform colored terminal text." -marker = "sys_platform == \"win32\" or platform_system == \"Windows\"" +marker = "platform_system == \"Windows\" or sys_platform == \"win32\"" name = "colorama" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" @@ -153,7 +153,7 @@ description = "Code coverage measurement for Python" name = "coverage" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" -version = "5.1" +version = "5.2" [package.extras] toml = ["toml"] @@ -175,7 +175,7 @@ description = "A utility for ensuring Google-style docstrings stay up to date wi name = "darglint" optional = false python-versions = ">=3.5,<4.0" -version = "1.4.0" +version = "1.5.1" [[package]] category = "dev" @@ -253,7 +253,7 @@ description = "the modular source code checker: pep8 pyflakes and co" name = "flake8" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" -version = "3.8.2" +version = "3.8.3" [package.dependencies] mccabe = ">=0.6.0,<0.7.0" @@ -284,7 +284,7 @@ description = "Flake8 plugin to forbid backslashes for line breaks" name = "flake8-broken-line" optional = false python-versions = ">=3.6,<4.0" -version = "0.2.0" +version = "0.2.1" [package.dependencies] flake8 = ">=3.5,<4.0" @@ -318,7 +318,7 @@ description = "A flake8 plugin to help you write better list/set/dict comprehens name = "flake8-comprehensions" optional = false python-versions = ">=3.5" -version = "3.2.2" +version = "3.2.3" [package.dependencies] flake8 = ">=3.0,<3.2.0 || >3.2.0,<4" @@ -488,7 +488,7 @@ description = "Internationalized Domain Names in Applications (IDNA)" name = "idna" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "2.9" +version = "2.10" [[package]] category = "dev" @@ -514,14 +514,14 @@ marker = "python_version < \"3.8\"" name = "importlib-metadata" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" -version = "1.6.0" +version = "1.7.0" [package.dependencies] zipp = ">=0.5" [package.extras] docs = ["sphinx", "rst.linker"] -testing = ["packaging", "importlib-resources"] +testing = ["packaging", "pep517", "importlib-resources (>=1.3)"] [[package]] category = "dev" @@ -531,11 +531,6 @@ optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" version = "4.3.21" -[package.dependencies] -[package.dependencies.toml] -optional = true -version = "*" - [package.extras] pipfile = ["pipreqs", "requirementslib"] pyproject = ["toml"] @@ -590,12 +585,12 @@ description = "A lightweight library for converting complex datatypes to and fro name = "marshmallow" optional = false python-versions = ">=3.5" -version = "3.6.1" +version = "3.7.0" [package.extras] -dev = ["pytest", "pytz", "simplejson", "mypy (0.770)", "flake8 (3.8.2)", "flake8-bugbear (20.1.4)", "pre-commit (>=2.4,<3.0)", "tox"] -docs = ["sphinx (3.0.4)", "sphinx-issues (1.2.0)", "alabaster (0.7.12)", "sphinx-version-warning (1.1.2)", "autodocsumm (0.1.13)"] -lint = ["mypy (0.770)", "flake8 (3.8.2)", "flake8-bugbear (20.1.4)", "pre-commit (>=2.4,<3.0)"] +dev = ["pytest", "pytz", "simplejson", "mypy (0.782)", "flake8 (3.8.3)", "flake8-bugbear (20.1.4)", "pre-commit (>=2.4,<3.0)", "tox"] +docs = ["sphinx (3.1.2)", "sphinx-issues (1.2.0)", "alabaster (0.7.12)", "sphinx-version-warning (1.1.2)", "autodocsumm (0.1.13)"] +lint = ["mypy (0.782)", "flake8 (3.8.3)", "flake8-bugbear (20.1.4)", "pre-commit (>=2.4,<3.0)"] tests = ["pytest", "pytz", "simplejson"] [[package]] @@ -631,7 +626,7 @@ description = "More routines for operating on iterables, beyond itertools" name = "more-itertools" optional = false python-versions = ">=3.5" -version = "8.3.0" +version = "8.4.0" [[package]] category = "dev" @@ -743,7 +738,7 @@ description = "library with cross-python path, ini-parsing, io, code, log facili name = "py" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.8.1" +version = "1.9.0" [[package]] category = "dev" @@ -867,7 +862,7 @@ description = "Pytest plugin to randomly order tests and control random.seed." name = "pytest-randomly" optional = false python-versions = ">=3.5" -version = "3.4.0" +version = "3.4.1" [package.dependencies] pytest = "*" @@ -893,7 +888,7 @@ description = "A Python Slugify application that handles Unicode" name = "python-slugify" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "4.0.0" +version = "4.0.1" [package.dependencies] text-unidecode = ">=1.3" @@ -923,7 +918,7 @@ description = "Python HTTP for Humans." name = "requests" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "2.23.0" +version = "2.24.0" [package.dependencies] certifi = ">=2017.4.17" @@ -1030,7 +1025,7 @@ description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" name = "sortedcontainers" optional = false python-versions = "*" -version = "2.1.0" +version = "2.2.2" [[package]] category = "dev" @@ -1038,7 +1033,7 @@ description = "Python documentation generator" name = "sphinx" optional = false python-versions = ">=3.5" -version = "3.1.1" +version = "3.1.2" [package.dependencies] Jinja2 = ">=2.3" @@ -1174,12 +1169,11 @@ category = "dev" description = "Manage dynamic plugins for Python applications" name = "stevedore" optional = false -python-versions = "*" -version = "1.32.0" +python-versions = ">=3.6" +version = "2.0.1" [package.dependencies] pbr = ">=2.0.0,<2.1.0 || >2.1.0" -six = ">=1.10.0" [[package]] category = "dev" @@ -1274,7 +1268,7 @@ description = "Measures the displayed width of unicode strings in a terminal" name = "wcwidth" optional = false python-versions = "*" -version = "0.2.3" +version = "0.2.5" [[package]] category = "dev" @@ -1323,7 +1317,7 @@ docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"] testing = ["jaraco.itertools", "func-timeout"] [metadata] -content-hash = "c8f269c19f760f70b312811905c78ca8112bdd5c097bae54b1d7185cc4c14d26" +content-hash = "a0e33b18af1d834201ce0452f2ea612e83c30309e7610fee6e8fd1bcf0c723a3" python-versions = "^3.6" [metadata.files] @@ -1360,8 +1354,8 @@ bandit = [ {file = "bandit-1.6.2.tar.gz", hash = "sha256:41e75315853507aa145d62a78a2a6c5e3240fe14ee7c601459d0df9418196065"}, ] certifi = [ - {file = "certifi-2020.4.5.1-py2.py3-none-any.whl", hash = "sha256:1d987a998c75633c40847cc966fcf5904906c920a7f17ef374f5aa4282abd304"}, - {file = "certifi-2020.4.5.1.tar.gz", hash = "sha256:51fcb31174be6e6664c5f69e3e1691a2d72a1a12e90f872cbdb1567eb47b6519"}, + {file = "certifi-2020.6.20-py2.py3-none-any.whl", hash = "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"}, + {file = "certifi-2020.6.20.tar.gz", hash = "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3"}, ] cffi = [ {file = "cffi-1.14.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1cae98a7054b5c9391eb3249b86e0e99ab1e02bb0cc0575da191aedadbdf4384"}, @@ -1409,44 +1403,47 @@ contextvars = [ {file = "contextvars-2.4.tar.gz", hash = "sha256:f38c908aaa59c14335eeea12abea5f443646216c4e29380d7bf34d2018e2c39e"}, ] coverage = [ - {file = "coverage-5.1-cp27-cp27m-macosx_10_12_x86_64.whl", hash = "sha256:0cb4be7e784dcdc050fc58ef05b71aa8e89b7e6636b99967fadbdba694cf2b65"}, - {file = "coverage-5.1-cp27-cp27m-macosx_10_13_intel.whl", hash = "sha256:c317eaf5ff46a34305b202e73404f55f7389ef834b8dbf4da09b9b9b37f76dd2"}, - {file = "coverage-5.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:b83835506dfc185a319031cf853fa4bb1b3974b1f913f5bb1a0f3d98bdcded04"}, - {file = "coverage-5.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5f2294dbf7875b991c381e3d5af2bcc3494d836affa52b809c91697449d0eda6"}, - {file = "coverage-5.1-cp27-cp27m-win32.whl", hash = "sha256:de807ae933cfb7f0c7d9d981a053772452217df2bf38e7e6267c9cbf9545a796"}, - {file = "coverage-5.1-cp27-cp27m-win_amd64.whl", hash = "sha256:bf9cb9a9fd8891e7efd2d44deb24b86d647394b9705b744ff6f8261e6f29a730"}, - {file = "coverage-5.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:acf3763ed01af8410fc36afea23707d4ea58ba7e86a8ee915dfb9ceff9ef69d0"}, - {file = "coverage-5.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:dec5202bfe6f672d4511086e125db035a52b00f1648d6407cc8e526912c0353a"}, - {file = "coverage-5.1-cp35-cp35m-macosx_10_12_x86_64.whl", hash = "sha256:7a5bdad4edec57b5fb8dae7d3ee58622d626fd3a0be0dfceda162a7035885ecf"}, - {file = "coverage-5.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:1601e480b9b99697a570cea7ef749e88123c04b92d84cedaa01e117436b4a0a9"}, - {file = "coverage-5.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:dbe8c6ae7534b5b024296464f387d57c13caa942f6d8e6e0346f27e509f0f768"}, - {file = "coverage-5.1-cp35-cp35m-win32.whl", hash = "sha256:a027ef0492ede1e03a8054e3c37b8def89a1e3c471482e9f046906ba4f2aafd2"}, - {file = "coverage-5.1-cp35-cp35m-win_amd64.whl", hash = "sha256:0e61d9803d5851849c24f78227939c701ced6704f337cad0a91e0972c51c1ee7"}, - {file = "coverage-5.1-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:2d27a3f742c98e5c6b461ee6ef7287400a1956c11421eb574d843d9ec1f772f0"}, - {file = "coverage-5.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:66460ab1599d3cf894bb6baee8c684788819b71a5dc1e8fa2ecc152e5d752019"}, - {file = "coverage-5.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:5c542d1e62eece33c306d66fe0a5c4f7f7b3c08fecc46ead86d7916684b36d6c"}, - {file = "coverage-5.1-cp36-cp36m-win32.whl", hash = "sha256:2742c7515b9eb368718cd091bad1a1b44135cc72468c731302b3d641895b83d1"}, - {file = "coverage-5.1-cp36-cp36m-win_amd64.whl", hash = "sha256:dead2ddede4c7ba6cb3a721870f5141c97dc7d85a079edb4bd8d88c3ad5b20c7"}, - {file = "coverage-5.1-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:01333e1bd22c59713ba8a79f088b3955946e293114479bbfc2e37d522be03355"}, - {file = "coverage-5.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:e1ea316102ea1e1770724db01998d1603ed921c54a86a2efcb03428d5417e489"}, - {file = "coverage-5.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:adeb4c5b608574a3d647011af36f7586811a2c1197c861aedb548dd2453b41cd"}, - {file = "coverage-5.1-cp37-cp37m-win32.whl", hash = "sha256:782caea581a6e9ff75eccda79287daefd1d2631cc09d642b6ee2d6da21fc0a4e"}, - {file = "coverage-5.1-cp37-cp37m-win_amd64.whl", hash = "sha256:00f1d23f4336efc3b311ed0d807feb45098fc86dee1ca13b3d6768cdab187c8a"}, - {file = "coverage-5.1-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:402e1744733df483b93abbf209283898e9f0d67470707e3c7516d84f48524f55"}, - {file = "coverage-5.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:a3f3654d5734a3ece152636aad89f58afc9213c6520062db3978239db122f03c"}, - {file = "coverage-5.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:6402bd2fdedabbdb63a316308142597534ea8e1895f4e7d8bf7476c5e8751fef"}, - {file = "coverage-5.1-cp38-cp38-win32.whl", hash = "sha256:8fa0cbc7ecad630e5b0f4f35b0f6ad419246b02bc750de7ac66db92667996d24"}, - {file = "coverage-5.1-cp38-cp38-win_amd64.whl", hash = "sha256:79a3cfd6346ce6c13145731d39db47b7a7b859c0272f02cdb89a3bdcbae233a0"}, - {file = "coverage-5.1-cp39-cp39-win32.whl", hash = "sha256:a82b92b04a23d3c8a581fc049228bafde988abacba397d57ce95fe95e0338ab4"}, - {file = "coverage-5.1-cp39-cp39-win_amd64.whl", hash = "sha256:bb28a7245de68bf29f6fb199545d072d1036a1917dca17a1e75bbb919e14ee8e"}, - {file = "coverage-5.1.tar.gz", hash = "sha256:f90bfc4ad18450c80b024036eaf91e4a246ae287701aaa88eaebebf150868052"}, + {file = "coverage-5.2-cp27-cp27m-macosx_10_13_intel.whl", hash = "sha256:d9ad0a988ae20face62520785ec3595a5e64f35a21762a57d115dae0b8fb894a"}, + {file = "coverage-5.2-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:4bb385a747e6ae8a65290b3df60d6c8a692a5599dc66c9fa3520e667886f2e10"}, + {file = "coverage-5.2-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:9702e2cb1c6dec01fb8e1a64c015817c0800a6eca287552c47a5ee0ebddccf62"}, + {file = "coverage-5.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:42fa45a29f1059eda4d3c7b509589cc0343cd6bbf083d6118216830cd1a51613"}, + {file = "coverage-5.2-cp27-cp27m-win32.whl", hash = "sha256:41d88736c42f4a22c494c32cc48a05828236e37c991bd9760f8923415e3169e4"}, + {file = "coverage-5.2-cp27-cp27m-win_amd64.whl", hash = "sha256:bbb387811f7a18bdc61a2ea3d102be0c7e239b0db9c83be7bfa50f095db5b92a"}, + {file = "coverage-5.2-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:3740b796015b889e46c260ff18b84683fa2e30f0f75a171fb10d2bf9fb91fc70"}, + {file = "coverage-5.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ebf2431b2d457ae5217f3a1179533c456f3272ded16f8ed0b32961a6d90e38ee"}, + {file = "coverage-5.2-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:d54d7ea74cc00482a2410d63bf10aa34ebe1c49ac50779652106c867f9986d6b"}, + {file = "coverage-5.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:87bdc8135b8ee739840eee19b184804e5d57f518578ffc797f5afa2c3c297913"}, + {file = "coverage-5.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:ed9a21502e9223f563e071759f769c3d6a2e1ba5328c31e86830368e8d78bc9c"}, + {file = "coverage-5.2-cp35-cp35m-win32.whl", hash = "sha256:509294f3e76d3f26b35083973fbc952e01e1727656d979b11182f273f08aa80b"}, + {file = "coverage-5.2-cp35-cp35m-win_amd64.whl", hash = "sha256:ca63dae130a2e788f2b249200f01d7fa240f24da0596501d387a50e57aa7075e"}, + {file = "coverage-5.2-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:5c74c5b6045969b07c9fb36b665c9cac84d6c174a809fc1b21bdc06c7836d9a0"}, + {file = "coverage-5.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:c32aa13cc3fe86b0f744dfe35a7f879ee33ac0a560684fef0f3e1580352b818f"}, + {file = "coverage-5.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:1e58fca3d9ec1a423f1b7f2aa34af4f733cbfa9020c8fe39ca451b6071237405"}, + {file = "coverage-5.2-cp36-cp36m-win32.whl", hash = "sha256:3b2c34690f613525672697910894b60d15800ac7e779fbd0fccf532486c1ba40"}, + {file = "coverage-5.2-cp36-cp36m-win_amd64.whl", hash = "sha256:a4d511012beb967a39580ba7d2549edf1e6865a33e5fe51e4dce550522b3ac0e"}, + {file = "coverage-5.2-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:32ecee61a43be509b91a526819717d5e5650e009a8d5eda8631a59c721d5f3b6"}, + {file = "coverage-5.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6f91b4492c5cde83bfe462f5b2b997cdf96a138f7c58b1140f05de5751623cf1"}, + {file = "coverage-5.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:bfcc811883699ed49afc58b1ed9f80428a18eb9166422bce3c31a53dba00fd1d"}, + {file = "coverage-5.2-cp37-cp37m-win32.whl", hash = "sha256:60a3d36297b65c7f78329b80120f72947140f45b5c7a017ea730f9112b40f2ec"}, + {file = "coverage-5.2-cp37-cp37m-win_amd64.whl", hash = "sha256:12eaccd86d9a373aea59869bc9cfa0ab6ba8b1477752110cb4c10d165474f703"}, + {file = "coverage-5.2-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:d82db1b9a92cb5c67661ca6616bdca6ff931deceebb98eecbd328812dab52032"}, + {file = "coverage-5.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:214eb2110217f2636a9329bc766507ab71a3a06a8ea30cdeebb47c24dce5972d"}, + {file = "coverage-5.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8a3decd12e7934d0254939e2bf434bf04a5890c5bf91a982685021786a08087e"}, + {file = "coverage-5.2-cp38-cp38-win32.whl", hash = "sha256:1dcebae667b73fd4aa69237e6afb39abc2f27520f2358590c1b13dd90e32abe7"}, + {file = "coverage-5.2-cp38-cp38-win_amd64.whl", hash = "sha256:f50632ef2d749f541ca8e6c07c9928a37f87505ce3a9f20c8446ad310f1aa87b"}, + {file = "coverage-5.2-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:7403675df5e27745571aba1c957c7da2dacb537c21e14007ec3a417bf31f7f3d"}, + {file = "coverage-5.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:0fc4e0d91350d6f43ef6a61f64a48e917637e1dcfcba4b4b7d543c628ef82c2d"}, + {file = "coverage-5.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:25fe74b5b2f1b4abb11e103bb7984daca8f8292683957d0738cd692f6a7cc64c"}, + {file = "coverage-5.2-cp39-cp39-win32.whl", hash = "sha256:d67599521dff98ec8c34cd9652cbcfe16ed076a2209625fca9dc7419b6370e5c"}, + {file = "coverage-5.2-cp39-cp39-win_amd64.whl", hash = "sha256:10f2a618a6e75adf64329f828a6a5b40244c1c50f5ef4ce4109e904e69c71bd2"}, + {file = "coverage-5.2.tar.gz", hash = "sha256:1874bdc943654ba46d28f179c1846f5710eda3aeb265ff029e0ac2b52daae404"}, ] curio = [ {file = "curio-1.2.tar.gz", hash = "sha256:90f320fafb3f5b791f25ffafa7b561cc980376de173afd575a2114380de7939b"}, ] darglint = [ - {file = "darglint-1.4.0-py3-none-any.whl", hash = "sha256:be8f4e722dd7c49d6b2abe1f23a2302e9b952fb88faab30fd030b7e79797901e"}, - {file = "darglint-1.4.0.tar.gz", hash = "sha256:ffcd02e23be54ef3eec47039a0da4290da4e78902ebd315f4bfb83d59c093437"}, + {file = "darglint-1.5.1-py3-none-any.whl", hash = "sha256:b37be3bea80d25fa015c002ab63d4100a676441dbb75af7cd1df69b1b9324d5f"}, + {file = "darglint-1.5.1.tar.gz", hash = "sha256:cb845b4cd046c9073be1f24935b6609abdc521270669ed7370ca0cdb112a7e1c"}, ] decorator = [ {file = "decorator-4.4.2-py2.py3-none-any.whl", hash = "sha256:41fa54c2a0cc4ba648be4fd43cff00aedf5b9465c9bf18d64325bc225f08f760"}, @@ -1472,15 +1469,15 @@ eradicate = [ {file = "eradicate-1.0.tar.gz", hash = "sha256:4ffda82aae6fd49dfffa777a857cb758d77502a1f2e0f54c9ac5155a39d2d01a"}, ] flake8 = [ - {file = "flake8-3.8.2-py2.py3-none-any.whl", hash = "sha256:ccaa799ef9893cebe69fdfefed76865aeaefbb94cb8545617b2298786a4de9a5"}, - {file = "flake8-3.8.2.tar.gz", hash = "sha256:c69ac1668e434d37a2d2880b3ca9aafd54b3a10a3ac1ab101d22f29e29cf8634"}, + {file = "flake8-3.8.3-py2.py3-none-any.whl", hash = "sha256:15e351d19611c887e482fb960eae4d44845013cc142d42896e9862f775d8cf5c"}, + {file = "flake8-3.8.3.tar.gz", hash = "sha256:f04b9fcbac03b0a3e58c0ab3a0ecc462e023a9faf046d57794184028123aa208"}, ] flake8-bandit = [ {file = "flake8_bandit-2.1.2.tar.gz", hash = "sha256:687fc8da2e4a239b206af2e54a90093572a60d0954f3054e23690739b0b0de3b"}, ] flake8-broken-line = [ - {file = "flake8-broken-line-0.2.0.tar.gz", hash = "sha256:550d217ebcdb1d3febc3a7dd5962b2deb4f809a5b0f10b7632b416c4877d2760"}, - {file = "flake8_broken_line-0.2.0-py3-none-any.whl", hash = "sha256:167130fcb4761755e9919c0bc8f984ff5790df1ff7a4447fed5c00b09ea6b4c3"}, + {file = "flake8-broken-line-0.2.1.tar.gz", hash = "sha256:414477070231a5aa05468d48db2742a594b53fbc1ecba28044646706a11fb861"}, + {file = "flake8_broken_line-0.2.1-py3-none-any.whl", hash = "sha256:75858359e3ccd4f1d92a9e7582aa5c9e4485cbc920dd05954703900cf907667e"}, ] flake8-bugbear = [ {file = "flake8-bugbear-19.8.0.tar.gz", hash = "sha256:d8c466ea79d5020cb20bf9f11cf349026e09517a42264f313d3f6fddb83e0571"}, @@ -1491,8 +1488,8 @@ flake8-commas = [ {file = "flake8_commas-2.0.0-py2.py3-none-any.whl", hash = "sha256:ee2141a3495ef9789a3894ed8802d03eff1eaaf98ce6d8653a7c573ef101935e"}, ] flake8-comprehensions = [ - {file = "flake8-comprehensions-3.2.2.tar.gz", hash = "sha256:e7db586bb6eb95afdfd87ed244c90e57ae1352db8ef0ad3012fca0200421e5df"}, - {file = "flake8_comprehensions-3.2.2-py3-none-any.whl", hash = "sha256:d08323aa801aef33477cd33f2f5ce3acb1aafd26803ab0d171d85d514c1273a2"}, + {file = "flake8-comprehensions-3.2.3.tar.gz", hash = "sha256:d5751acc0f7364794c71d06f113f4686d6e2e26146a50fa93130b9f200fe160d"}, + {file = "flake8_comprehensions-3.2.3-py3-none-any.whl", hash = "sha256:44eaae9894aa15f86e0c86df1e218e7917494fab6f96d28f96a029c460f17d92"}, ] flake8-debugger = [ {file = "flake8-debugger-3.2.1.tar.gz", hash = "sha256:712d7c1ff69ddf3f0130e94cc88c2519e720760bce45e8c330bfdcb61ab4090d"}, @@ -1544,8 +1541,8 @@ gitpython = [ {file = "GitPython-3.1.3.tar.gz", hash = "sha256:e107af4d873daed64648b4f4beb89f89f0cfbe3ef558fc7821ed2331c2f8da1a"}, ] idna = [ - {file = "idna-2.9-py2.py3-none-any.whl", hash = "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa"}, - {file = "idna-2.9.tar.gz", hash = "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb"}, + {file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"}, + {file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"}, ] imagesize = [ {file = "imagesize-1.2.0-py2.py3-none-any.whl", hash = "sha256:6965f19a6a2039c7d48bca7dba2473069ff854c36ae6f19d2cde309d998228a1"}, @@ -1566,8 +1563,8 @@ immutables = [ {file = "immutables-0.14.tar.gz", hash = "sha256:a0a1cc238b678455145bae291d8426f732f5255537ed6a5b7645949704c70a78"}, ] importlib-metadata = [ - {file = "importlib_metadata-1.6.0-py2.py3-none-any.whl", hash = "sha256:2a688cbaa90e0cc587f1df48bdc97a6eadccdcd9c35fb3f976a09e3b5016d90f"}, - {file = "importlib_metadata-1.6.0.tar.gz", hash = "sha256:34513a8a0c4962bc66d35b359558fd8a5e10cd472d37aec5f66858addef32c1e"}, + {file = "importlib_metadata-1.7.0-py2.py3-none-any.whl", hash = "sha256:dc15b2969b4ce36305c51eebe62d418ac7791e9a157911d58bfb1f9ccd8e2070"}, + {file = "importlib_metadata-1.7.0.tar.gz", hash = "sha256:90bb658cdbbf6d1735b6341ce708fc7024a3e14e99ffdc5783edea9f9b077f83"}, ] isort = [ {file = "isort-4.3.21-py2.py3-none-any.whl", hash = "sha256:6e811fcb295968434526407adb8796944f1988c5b65e8139058f2014cbe100fd"}, @@ -1620,8 +1617,8 @@ markupsafe = [ {file = "MarkupSafe-1.1.1.tar.gz", hash = "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b"}, ] marshmallow = [ - {file = "marshmallow-3.6.1-py2.py3-none-any.whl", hash = "sha256:9aa20f9b71c992b4782dad07c51d92884fd0f7c5cb9d3c737bea17ec1bad765f"}, - {file = "marshmallow-3.6.1.tar.gz", hash = "sha256:35ee2fb188f0bd9fc1cf9ac35e45fd394bd1c153cee430745a465ea435514bd5"}, + {file = "marshmallow-3.7.0-py2.py3-none-any.whl", hash = "sha256:0f3a630f6a2fd124929f1bdcb5df65bd14cc8f49f52a18d0bdcfa0c42414e4a7"}, + {file = "marshmallow-3.7.0.tar.gz", hash = "sha256:ba949379cb6ef73655f72075e82b31cf57012a5557ede642fc8614ab0354f869"}, ] marshmallow-polyfield = [ {file = "marshmallow-polyfield-5.9.tar.gz", hash = "sha256:448f4b1ac5cbd671c0fb8a5452e99da7c0e8be924dd2cda2a21ee59457a4748f"}, @@ -1635,8 +1632,8 @@ mistune = [ {file = "mistune-0.8.4.tar.gz", hash = "sha256:59a3429db53c50b5c6bcc8a07f8848cb00d7dc8bdb431a4ab41920d201d4756e"}, ] more-itertools = [ - {file = "more-itertools-8.3.0.tar.gz", hash = "sha256:558bb897a2232f5e4f8e2399089e35aecb746e1f9191b6584a151647e89267be"}, - {file = "more_itertools-8.3.0-py3-none-any.whl", hash = "sha256:7818f596b1e87be009031c7653d01acc46ed422e6656b394b0f765ce66ed4982"}, + {file = "more-itertools-8.4.0.tar.gz", hash = "sha256:68c70cc7167bdf5c7c9d8f6954a7837089c6a36bf565383919bb595efb8a17e5"}, + {file = "more_itertools-8.4.0-py3-none-any.whl", hash = "sha256:b78134b2063dd214000685165d81c154522c3ee0a1c0d4d113c80361c234c5a2"}, ] mypy = [ {file = "mypy-0.782-cp35-cp35m-macosx_10_6_x86_64.whl", hash = "sha256:2c6cde8aa3426c1682d35190b59b71f661237d74b053822ea3d748e2c9578a7c"}, @@ -1683,8 +1680,8 @@ pluggy = [ {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, ] py = [ - {file = "py-1.8.1-py2.py3-none-any.whl", hash = "sha256:c20fdd83a5dbc0af9efd622bee9a5564e278f6380fffcacc43ba6f43db2813b0"}, - {file = "py-1.8.1.tar.gz", hash = "sha256:5e27081401262157467ad6e7f851b7aa402c5852dbcb3dae06768434de5752aa"}, + {file = "py-1.9.0-py2.py3-none-any.whl", hash = "sha256:366389d1db726cd2fcfc79732e75410e5fe4d31db13692115529d34069a043c2"}, + {file = "py-1.9.0.tar.gz", hash = "sha256:9ca6883ce56b4e8da7e79ac18787889fa5206c79dcc67fb065376cd2fe03f342"}, ] pycodestyle = [ {file = "pycodestyle-2.6.0-py2.py3-none-any.whl", hash = "sha256:2295e7b2f6b5bd100585ebcb1f616591b652db8a741695b3d8f5d28bdc934367"}, @@ -1726,15 +1723,15 @@ pytest-mypy-plugins = [ {file = "pytest_mypy_plugins-1.4.0-py3-none-any.whl", hash = "sha256:baa43948e9873220876fae86dbefc69727803b2df8c20f8164ff0be9823e91d7"}, ] pytest-randomly = [ - {file = "pytest-randomly-3.4.0.tar.gz", hash = "sha256:e44a69623237e47cc4ee77da9c04c6b505ed1a7b00656dc1409f8344c707b87b"}, - {file = "pytest_randomly-3.4.0-py3-none-any.whl", hash = "sha256:4e02887ba52f021cc8d5429e91e93be2b5df4adf38bf1715c7c153968b260b59"}, + {file = "pytest-randomly-3.4.1.tar.gz", hash = "sha256:5fd0dbeeb218a7ce029690a8100453cd8d6a7972cf9d8e657690352692e92c69"}, + {file = "pytest_randomly-3.4.1-py3-none-any.whl", hash = "sha256:2c4df1390db72a33a4f44fac0c780e7883cd5968238efa2a2bdbdd54e3fc6681"}, ] pytest-subtests = [ {file = "pytest-subtests-0.3.1.tar.gz", hash = "sha256:f673d8536eb8a153dd9c871b55c06aa3dea55cbdcf3bb3cdd4c4149a4e81606f"}, {file = "pytest_subtests-0.3.1-py3-none-any.whl", hash = "sha256:c3727c22bbbe29268e3552231da51704cc179e63e59d8e857077c19e77e85210"}, ] python-slugify = [ - {file = "python-slugify-4.0.0.tar.gz", hash = "sha256:a8fc3433821140e8f409a9831d13ae5deccd0b033d4744d94b31fea141bdd84c"}, + {file = "python-slugify-4.0.1.tar.gz", hash = "sha256:69a517766e00c1268e5bbfc0d010a0a8508de0b18d30ad5a1ff357f8ae724270"}, ] pytz = [ {file = "pytz-2020.1-py2.py3-none-any.whl", hash = "sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed"}, @@ -1754,9 +1751,8 @@ pyyaml = [ {file = "PyYAML-5.3.1.tar.gz", hash = "sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d"}, ] requests = [ - {file = "requests-2.23.0-py2.7.egg", hash = "sha256:5d2d0ffbb515f39417009a46c14256291061ac01ba8f875b90cad137de83beb4"}, - {file = "requests-2.23.0-py2.py3-none-any.whl", hash = "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee"}, - {file = "requests-2.23.0.tar.gz", hash = "sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6"}, + {file = "requests-2.24.0-py2.py3-none-any.whl", hash = "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898"}, + {file = "requests-2.24.0.tar.gz", hash = "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b"}, ] restructuredtext-lint = [ {file = "restructuredtext_lint-1.3.1.tar.gz", hash = "sha256:470e53b64817211a42805c3a104d2216f6f5834b22fe7adb637d1de4d6501fb8"}, @@ -1807,12 +1803,12 @@ snowballstemmer = [ {file = "snowballstemmer-2.0.0.tar.gz", hash = "sha256:df3bac3df4c2c01363f3dd2cfa78cce2840a79b9f1c2d2de9ce8d31683992f52"}, ] sortedcontainers = [ - {file = "sortedcontainers-2.1.0-py2.py3-none-any.whl", hash = "sha256:d9e96492dd51fae31e60837736b38fe42a187b5404c16606ff7ee7cd582d4c60"}, - {file = "sortedcontainers-2.1.0.tar.gz", hash = "sha256:974e9a32f56b17c1bac2aebd9dcf197f3eb9cd30553c5852a3187ad162e1a03a"}, + {file = "sortedcontainers-2.2.2-py2.py3-none-any.whl", hash = "sha256:c633ebde8580f241f274c1f8994a665c0e54a17724fecd0cae2f079e09c36d3f"}, + {file = "sortedcontainers-2.2.2.tar.gz", hash = "sha256:4e73a757831fc3ca4de2859c422564239a31d8213d09a2a666e375807034d2ba"}, ] sphinx = [ - {file = "Sphinx-3.1.1-py3-none-any.whl", hash = "sha256:97c9e3bcce2f61d9f5edf131299ee9d1219630598d9f9a8791459a4d9e815be5"}, - {file = "Sphinx-3.1.1.tar.gz", hash = "sha256:74fbead182a611ce1444f50218a1c5fc70b6cc547f64948f5182fb30a2a20258"}, + {file = "Sphinx-3.1.2-py3-none-any.whl", hash = "sha256:97dbf2e31fc5684bb805104b8ad34434ed70e6c588f6896991b2fdfd2bef8c00"}, + {file = "Sphinx-3.1.2.tar.gz", hash = "sha256:b9daeb9b39aa1ffefc2809b43604109825300300b987a24f45976c001ba1a8fd"}, ] sphinx-autodoc-typehints = [ {file = "sphinx-autodoc-typehints-1.11.0.tar.gz", hash = "sha256:bbf0b203f1019b0f9843ee8eef0cff856dc04b341f6dbe1113e37f2ebf243e11"}, @@ -1851,8 +1847,8 @@ sphinxcontrib-serializinghtml = [ {file = "sphinxcontrib_serializinghtml-1.1.4-py2.py3-none-any.whl", hash = "sha256:f242a81d423f59617a8e5cf16f5d4d74e28ee9a66f9e5b637a18082991db5a9a"}, ] stevedore = [ - {file = "stevedore-1.32.0-py2.py3-none-any.whl", hash = "sha256:a4e7dc759fb0f2e3e2f7d8ffe2358c19d45b9b8297f393ef1256858d82f69c9b"}, - {file = "stevedore-1.32.0.tar.gz", hash = "sha256:18afaf1d623af5950cc0f7e75e70f917784c73b652a34a12d90b309451b5500b"}, + {file = "stevedore-2.0.1-py3-none-any.whl", hash = "sha256:c4724f8d7b8f6be42130663855d01a9c2414d6046055b5a65ab58a0e38637688"}, + {file = "stevedore-2.0.1.tar.gz", hash = "sha256:609912b87df5ad338ff8e44d13eaad4f4170a65b79ae9cb0aa5632598994a1b7"}, ] testfixtures = [ {file = "testfixtures-6.14.1-py2.py3-none-any.whl", hash = "sha256:30566e24a1b34e4d3f8c13abf62557d01eeb4480bcb8f1745467bfb0d415a7d9"}, @@ -1908,8 +1904,8 @@ urllib3 = [ {file = "urllib3-1.25.9.tar.gz", hash = "sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527"}, ] wcwidth = [ - {file = "wcwidth-0.2.3-py2.py3-none-any.whl", hash = "sha256:980fbf4f3c196c0f329cdcd1e84c554d6a211f18e252e525a0cf4223154a41d6"}, - {file = "wcwidth-0.2.3.tar.gz", hash = "sha256:edbc2b718b4db6cdf393eefe3a420183947d6aa312505ce6754516f458ff8830"}, + {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, + {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, ] wemake-python-styleguide = [ {file = "wemake-python-styleguide-0.14.0.tar.gz", hash = "sha256:633d738b65c7ddf0c2b9e26e9d889d76f0f1993a82902821da359f08b233dbc8"}, diff --git a/pyproject.toml b/pyproject.toml index f1606b630..0f8b05fcc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -62,6 +62,10 @@ flake8-pytest-style = "^1.2" flake8-pyi = "^20.5" nitpick = "^0.22" +# TODO: remove after +# https://github.com/gforcada/flake8-isort/issues/88 +isort = "<5.0" + anyio = "^1.4" curio = "^1.2" trio = "^0.16" diff --git a/returns/_generated/futures/_future.py b/returns/_generated/futures/_future.py index 3fc51e9c4..c243abab5 100644 --- a/returns/_generated/futures/_future.py +++ b/returns/_generated/futures/_future.py @@ -1,6 +1,7 @@ from typing import TYPE_CHECKING, Awaitable, Callable, TypeVar from returns.io import IO +from returns.primitives.hkt import Kind1, dekind if TYPE_CHECKING: from returns.future import Future # noqa: F401 @@ -26,11 +27,11 @@ async def async_apply( async def async_bind( - function: Callable[[_ValueType], 'Future[_NewValueType]'], + function: Callable[[_ValueType], Kind1['Future', _NewValueType]], inner_value: Awaitable[_ValueType], ) -> _NewValueType: """Async binds a container over a value.""" - return (await function(await inner_value))._inner_value + return (await dekind(function(await inner_value)))._inner_value async def async_bind_awaitable( diff --git a/returns/_generated/futures/_future_result.py b/returns/_generated/futures/_future_result.py index 9bc1be6e3..c2a02ea51 100644 --- a/returns/_generated/futures/_future_result.py +++ b/returns/_generated/futures/_future_result.py @@ -1,6 +1,7 @@ -from typing import TYPE_CHECKING, Any, Awaitable, Callable, TypeVar, Union +from typing import TYPE_CHECKING, Any, Awaitable, Callable, TypeVar from returns.io import IO, IOResult +from returns.primitives.hkt import Kind2, dekind from returns.result import Failure, Result, Success if TYPE_CHECKING: @@ -33,14 +34,14 @@ async def async_apply( async def async_bind( function: Callable[ [_ValueType], - 'FutureResult[_NewValueType, _ErrorType]', + Kind2['FutureResult', _NewValueType, _ErrorType], ], inner_value: Awaitable[Result[_ValueType, _ErrorType]], ) -> Result[_NewValueType, _ErrorType]: """Async binds a container over a value.""" container = await inner_value if isinstance(container, Result.success_type): - return (await function(container.unwrap()))._inner_value + return (await dekind(function(container.unwrap())))._inner_value return container # type: ignore[return-value] @@ -144,36 +145,17 @@ async def async_alt( async def async_rescue( - function: Callable[[_ErrorType], 'FutureResult[_ValueType, _NewErrorType]'], + function: Callable[ + [_ErrorType], + Kind2['FutureResult', _ValueType, _NewErrorType], + ], inner_value: Awaitable[Result[_ValueType, _ErrorType]], ) -> Result[_ValueType, _NewErrorType]: """Async rescues a function returning a container over a value.""" container = await inner_value if isinstance(container, Result.success_type): return container - return (await function(container.failure()))._inner_value - - -async def async_value_or( - container: 'FutureResult[_ValueType, _ErrorType]', - default_value: _NewValueType, -) -> IO[Union[_ValueType, _NewValueType]]: - """Return async value or default value.""" - return IO((await container._inner_value).value_or(default_value)) - - -async def async_unwrap( - container: 'FutureResult[_ValueType, _ErrorType]', -) -> IO[_ValueType]: - """Async unwrap a container.""" - return IO((await container._inner_value).unwrap()) - - -async def async_failure( - container: 'FutureResult[_ValueType, _ErrorType]', -) -> IO[_ErrorType]: - """Async unwrap an error from container.""" - return IO((await container._inner_value).failure()) + return (await dekind(function(container.failure())))._inner_value async def async_from_success( diff --git a/returns/_generated/futures/_reader_future_result.py b/returns/_generated/futures/_reader_future_result.py index 75d9302a5..68a6f55f1 100644 --- a/returns/_generated/futures/_reader_future_result.py +++ b/returns/_generated/futures/_reader_future_result.py @@ -15,10 +15,10 @@ async def async_bind_async( function: Callable[ [_ValueType], Awaitable[ - 'RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType]', + 'RequiresContextFutureResult[_NewValueType, _ErrorType, _EnvType]', ], ], - container: 'RequiresContextFutureResult[_EnvType, _ValueType, _ErrorType]', + container: 'RequiresContextFutureResult[_ValueType, _ErrorType, _EnvType]', deps: _EnvType, ) -> Result[_NewValueType, _ErrorType]: """Async binds a coroutine with container over a value.""" diff --git a/returns/_generated/pipeline/flow.py b/returns/_generated/pipeline/flow.py index aaf5b66a2..593d20a25 100644 --- a/returns/_generated/pipeline/flow.py +++ b/returns/_generated/pipeline/flow.py @@ -1,17 +1,9 @@ from functools import reduce -from typing import TypeVar from returns.functions import compose -_InstanceType = TypeVar('_InstanceType') -_PipelineStepType = TypeVar('_PipelineStepType') -_ReturnType = TypeVar('_ReturnType') - -def _flow( - instance: _InstanceType, - *functions: _PipelineStepType, -) -> _ReturnType: +def _flow(instance, *functions): """ Allows to compose a value and up to multiple functions that use this value. @@ -21,6 +13,11 @@ def _flow( We use a custom ``mypy`` plugin to make sure types are correct. Otherwise, it is currently impossible to properly type this function. + Currently, ``flow`` has a hard limit of 21 steps. + Because, it is not possible to type it otherwise. + We need a hard limit. + See: https://github.com/dry-python/returns/issues/461 + Here's how it should be used: .. code:: python @@ -43,6 +40,5 @@ def _flow( - https://github.com/gcanti/fp-ts/blob/master/src/pipeable.ts Requires our :ref:`mypy plugin `. - """ - return reduce(compose, functions)(instance) # type: ignore + return reduce(compose, functions)(instance) diff --git a/returns/_generated/pipeline/flow.pyi b/returns/_generated/pipeline/flow.pyi new file mode 100644 index 000000000..75e5bf72a --- /dev/null +++ b/returns/_generated/pipeline/flow.pyi @@ -0,0 +1,51 @@ +from typing import TypeVar + +_InstanceType = TypeVar('_InstanceType') +_ReturnType = TypeVar('_ReturnType') + +_PipelineStepType1 = TypeVar('_PipelineStepType1') +_PipelineStepType2 = TypeVar('_PipelineStepType2') +_PipelineStepType3 = TypeVar('_PipelineStepType3') +_PipelineStepType4 = TypeVar('_PipelineStepType4') +_PipelineStepType5 = TypeVar('_PipelineStepType5') +_PipelineStepType6 = TypeVar('_PipelineStepType6') +_PipelineStepType7 = TypeVar('_PipelineStepType7') +_PipelineStepType8 = TypeVar('_PipelineStepType8') +_PipelineStepType9 = TypeVar('_PipelineStepType9') +_PipelineStepType10 = TypeVar('_PipelineStepType10') +_PipelineStepType11 = TypeVar('_PipelineStepType11') +_PipelineStepType12 = TypeVar('_PipelineStepType12') +_PipelineStepType13 = TypeVar('_PipelineStepType13') +_PipelineStepType14 = TypeVar('_PipelineStepType14') +_PipelineStepType15 = TypeVar('_PipelineStepType15') +_PipelineStepType16 = TypeVar('_PipelineStepType16') +_PipelineStepType17 = TypeVar('_PipelineStepType17') +_PipelineStepType18 = TypeVar('_PipelineStepType18') +_PipelineStepType19 = TypeVar('_PipelineStepType19') +_PipelineStepType20 = TypeVar('_PipelineStepType20') + + +def _flow( + instance: _InstanceType, + function1: _PipelineStepType1, + function2: _PipelineStepType2 = ..., + function3: _PipelineStepType3 = ..., + function4: _PipelineStepType4 = ..., + function5: _PipelineStepType5 = ..., + function6: _PipelineStepType6 = ..., + function7: _PipelineStepType7 = ..., + function8: _PipelineStepType8 = ..., + function9: _PipelineStepType9 = ..., + function10: _PipelineStepType10 = ..., + function11: _PipelineStepType11 = ..., + function12: _PipelineStepType12 = ..., + function13: _PipelineStepType13 = ..., + function14: _PipelineStepType14 = ..., + function15: _PipelineStepType15 = ..., + function16: _PipelineStepType16 = ..., + function17: _PipelineStepType17 = ..., + function18: _PipelineStepType18 = ..., + function19: _PipelineStepType19 = ..., + function20: _PipelineStepType20 = ..., +) -> _ReturnType: + ... diff --git a/returns/_generated/pipeline/managed.pyi b/returns/_generated/pipeline/managed.pyi index 4d7f6988f..8cf3fcbdc 100644 --- a/returns/_generated/pipeline/managed.pyi +++ b/returns/_generated/pipeline/managed.pyi @@ -49,15 +49,15 @@ def _managed( def _managed( use: Callable[ [_ValueType], - ReaderIOResult[_EnvType, _NewValueType, _ErrorType], + ReaderIOResult[_NewValueType, _ErrorType, _EnvType], ], release: Callable[ [_ValueType, Result[_NewValueType, _ErrorType]], - ReaderIOResult[_EnvType, None, _ErrorType], + ReaderIOResult[None, _ErrorType, _EnvType], ], ) -> Callable[ - [ReaderIOResult[_EnvType, _ValueType, _ErrorType]], - ReaderIOResult[_EnvType, _NewValueType, _ErrorType], + [ReaderIOResult[_ValueType, _ErrorType, _EnvType]], + ReaderIOResult[_NewValueType, _ErrorType, _EnvType], ]: ... @@ -66,14 +66,14 @@ def _managed( def _managed( use: Callable[ [_ValueType], - ReaderFutureResult[_EnvType, _NewValueType, _ErrorType], + ReaderFutureResult[_NewValueType, _ErrorType, _EnvType], ], release: Callable[ [_ValueType, Result[_NewValueType, _ErrorType]], - ReaderFutureResult[_EnvType, None, _ErrorType], + ReaderFutureResult[None, _ErrorType, _EnvType], ], ) -> Callable[ - [ReaderFutureResult[_EnvType, _ValueType, _ErrorType]], - ReaderFutureResult[_EnvType, _NewValueType, _ErrorType], + [ReaderFutureResult[_ValueType, _ErrorType, _EnvType]], + ReaderFutureResult[_NewValueType, _ErrorType, _EnvType], ]: ... diff --git a/returns/_generated/pointfree/alt.py b/returns/_generated/pointfree/alt.py deleted file mode 100644 index 9b8cc01ce..000000000 --- a/returns/_generated/pointfree/alt.py +++ /dev/null @@ -1,28 +0,0 @@ -def _alt(function): - """ - Lifts function to be wrapped in a container for better composition. - - In other words, it modifies the function's - signature from: ``a -> b`` to: ``Container[a] -> Container[b]`` - - Works similar to :meth:`returns.primitives.interfaces.Altable.alt`, - but has inverse semantics. - - This is how it should be used: - - .. code:: python - - >>> from returns.result import Result, Success, Failure - >>> from returns.pointfree import alt - - >>> def example(argument: int) -> float: - ... return argument / 2 - - >>> first: Result[str, int] = Success('a') - >>> second: Result[str, int] = Failure(1) - - >>> assert alt(example)(first) == Success('a') - >>> assert alt(example)(second) == Failure(0.5) - - """ - return lambda container: container.alt(function) diff --git a/returns/_generated/pointfree/alt.pyi b/returns/_generated/pointfree/alt.pyi deleted file mode 100644 index 267e26eea..000000000 --- a/returns/_generated/pointfree/alt.pyi +++ /dev/null @@ -1,78 +0,0 @@ -from typing import Callable, TypeVar, overload - -from typing_extensions import Protocol - -from returns.context import ( - RequiresContextFutureResult, - RequiresContextIOResult, - RequiresContextResult, -) -from returns.future import FutureResult -from returns.io import IOResult -from returns.result import Result - -_ValueType = TypeVar('_ValueType') -_ErrorType = TypeVar('_ErrorType', contravariant=True) -_NewErrorType = TypeVar('_NewErrorType', covariant=True) -_EnvType = TypeVar('_EnvType', contravariant=True) - - -class _Altable(Protocol[_ErrorType, _NewErrorType]): - """ - Represents type overloads for ``ret_type`` based on an error type. - - Contains all containers we have. - - It does not exist in runtime. - It is also completely removed from typing with the help of the mypy plugin. - """ - - @overload - def __call__( - self, - container: RequiresContextResult[_EnvType, _ValueType, _ErrorType], - ) -> RequiresContextResult[_EnvType, _ValueType, _NewErrorType]: - ... - - @overload - def __call__( - self, - container: RequiresContextIOResult[_EnvType, _ValueType, _ErrorType], - ) -> RequiresContextIOResult[_EnvType, _ValueType, _NewErrorType]: - ... - - @overload - def __call__( - self, - container: RequiresContextFutureResult[ - _EnvType, _ValueType, _ErrorType, - ], - ) -> RequiresContextFutureResult[_EnvType, _ValueType, _NewErrorType]: - ... - - @overload - def __call__( - self, - container: Result[_ValueType, _ErrorType], - ) -> Result[_ValueType, _NewErrorType]: - ... - - @overload - def __call__( - self, - container: IOResult[_ValueType, _ErrorType], - ) -> IOResult[_ValueType, _NewErrorType]: - ... - - @overload - def __call__( - self, - container: FutureResult[_ValueType, _ErrorType], - ) -> FutureResult[_ValueType, _NewErrorType]: - ... - - -def _alt( - function: Callable[[_ErrorType], _NewErrorType], -) -> _Altable[_ErrorType, _NewErrorType]: - ... diff --git a/returns/_generated/pointfree/apply.py b/returns/_generated/pointfree/apply.py deleted file mode 100644 index 3236681fe..000000000 --- a/returns/_generated/pointfree/apply.py +++ /dev/null @@ -1,27 +0,0 @@ -def _apply(container): - """ - Turns container containing a function into a callable. - - In other words, it modifies the function - signature from: ``Container[a -> b]`` to: ``Container[a] -> Container[b]`` - - This is how it should be used: - - .. code:: python - - >>> from returns.pointfree import apply - >>> from returns.maybe import Some, Nothing - - >>> def example(argument: int) -> int: - ... return argument + 1 - - >>> assert apply(Some(example))(Some(1)) == Some(2) - >>> assert apply(Some(example))(Nothing) == Nothing - >>> assert apply(Nothing)(Some(1)) == Nothing - >>> assert apply(Nothing)(Nothing) == Nothing - - Note, that this function works for all containers with ``.apply`` method. - See :class:`returns.primitives.interfaces.Applicative` for more info. - - """ - return lambda other: other.apply(container) diff --git a/returns/_generated/pointfree/apply.pyi b/returns/_generated/pointfree/apply.pyi deleted file mode 100644 index ba13fe64a..000000000 --- a/returns/_generated/pointfree/apply.pyi +++ /dev/null @@ -1,132 +0,0 @@ -from typing import Callable, TypeVar, overload - -from returns.context import ( - RequiresContext, - RequiresContextFutureResult, - RequiresContextIOResult, - RequiresContextResult, -) -from returns.future import Future, FutureResult -from returns.io import IO, IOResult -from returns.maybe import Maybe -from returns.result import Result - -_ValueType = TypeVar('_ValueType') -_ErrorType = TypeVar('_ErrorType') -_NewValueType = TypeVar('_NewValueType') -_EnvType = TypeVar('_EnvType') - - -@overload -def _apply( - container: Maybe[Callable[[_ValueType], _NewValueType]], -) -> Callable[[Maybe[_ValueType]], Maybe[_NewValueType]]: - ... - - -@overload -def _apply( - container: IO[Callable[[_ValueType], _NewValueType]], -) -> Callable[[IO[_ValueType]], IO[_NewValueType]]: - ... - - -@overload -def _apply( - container: RequiresContext[_EnvType, Callable[[_ValueType], _NewValueType]], -) -> Callable[ - [RequiresContext[_EnvType, _ValueType]], - RequiresContext[_EnvType, _NewValueType], -]: - ... - - -@overload -def _apply( - container: RequiresContextResult[ - _EnvType, - Callable[[_ValueType], _NewValueType], - _ErrorType, - ], -) -> Callable[ - [RequiresContextResult[_EnvType, _ValueType, _ErrorType]], - RequiresContextResult[_EnvType, _NewValueType, _ErrorType], -]: - ... - - -@overload -def _apply( - container: RequiresContextIOResult[ - _EnvType, - Callable[[_ValueType], _NewValueType], - _ErrorType, - ], -) -> Callable[ - [RequiresContextIOResult[_EnvType, _ValueType, _ErrorType]], - RequiresContextIOResult[_EnvType, _NewValueType, _ErrorType], -]: - ... - - -@overload -def _apply( - container: RequiresContextFutureResult[ - _EnvType, - Callable[[_ValueType], _NewValueType], - _ErrorType, - ], -) -> Callable[ - [RequiresContextFutureResult[_EnvType, _ValueType, _ErrorType]], - RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType], -]: - ... - - -@overload -def _apply( - container: Result[ - Callable[[_ValueType], _NewValueType], - _ErrorType, - ], -) -> Callable[ - [Result[_ValueType, _ErrorType]], - Result[_NewValueType, _ErrorType], -]: - ... - - -@overload -def _apply( - container: IOResult[ - Callable[[_ValueType], _NewValueType], - _ErrorType, - ], -) -> Callable[ - [IOResult[_ValueType, _ErrorType]], - IOResult[_NewValueType, _ErrorType], -]: - ... - - -@overload -def _apply( - container: Future[Callable[[_ValueType], _NewValueType]], -) -> Callable[ - [Future[_ValueType]], - Future[_NewValueType], -]: - ... - - -@overload -def _apply( - container: FutureResult[ - Callable[[_ValueType], _NewValueType], - _ErrorType, - ], -) -> Callable[ - [FutureResult[_ValueType, _ErrorType]], - FutureResult[_NewValueType, _ErrorType], -]: - ... diff --git a/returns/_generated/pointfree/bind.py b/returns/_generated/pointfree/bind.py deleted file mode 100644 index b77685ba8..000000000 --- a/returns/_generated/pointfree/bind.py +++ /dev/null @@ -1,28 +0,0 @@ -def _bind(function): - """ - Turns function's input parameter from a regular value to a container. - - In other words, it modifies the function - signature from: ``a -> Container[b]`` to: ``Container[a] -> Container[b]`` - - Similar to :func:`returns.pointfree.rescue`, - but works for successful containers. - - This is how it should be used: - - .. code:: python - - >>> from returns.pointfree import bind - >>> from returns.maybe import Maybe, Some, Nothing - - >>> def example(argument: int) -> Maybe[int]: - ... return Some(argument + 1) - - >>> assert bind(example)(Some(1)) == Some(2) - >>> assert bind(example)(Nothing) == Nothing - - Note, that this function works for all containers with ``.bind`` method. - See :class:`returns.primitives.interfaces.Bindable` for more info. - - """ - return lambda container: container.bind(function) diff --git a/returns/_generated/pointfree/bind.pyi b/returns/_generated/pointfree/bind.pyi deleted file mode 100644 index 971f7887f..000000000 --- a/returns/_generated/pointfree/bind.pyi +++ /dev/null @@ -1,117 +0,0 @@ -from typing import Callable, TypeVar, overload - -from returns.context import ( - RequiresContext, - RequiresContextFutureResult, - RequiresContextIOResult, - RequiresContextResult, -) -from returns.future import Future, FutureResult -from returns.io import IO, IOResult -from returns.maybe import Maybe -from returns.result import Result - -_ValueType = TypeVar('_ValueType', contravariant=True) -_ErrorType = TypeVar('_ErrorType') -_NewValueType = TypeVar('_NewValueType', covariant=True) -_EnvType = TypeVar('_EnvType', contravariant=True) - - -@overload -def _bind( - function: Callable[[_ValueType], Maybe[_NewValueType]], -) -> Callable[[Maybe[_ValueType]], Maybe[_NewValueType]]: - ... - - -@overload -def _bind( - function: Callable[[_ValueType], IO[_NewValueType]], -) -> Callable[[IO[_ValueType]], IO[_NewValueType]]: - ... - - -@overload -def _bind( - function: Callable[[_ValueType], RequiresContext[_EnvType, _NewValueType]], -) -> Callable[ - [RequiresContext[_EnvType, _ValueType]], - RequiresContext[_EnvType, _NewValueType], -]: - ... - - -@overload -def _bind( - function: Callable[ - [_ValueType], - RequiresContextResult[_EnvType, _NewValueType, _ErrorType], - ], -) -> Callable[ - [RequiresContextResult[_EnvType, _ValueType, _ErrorType]], - RequiresContextResult[_EnvType, _NewValueType, _ErrorType], -]: - ... - - -@overload -def _bind( - function: Callable[ - [_ValueType], - RequiresContextIOResult[_EnvType, _NewValueType, _ErrorType], - ], -) -> Callable[ - [RequiresContextIOResult[_EnvType, _ValueType, _ErrorType]], - RequiresContextIOResult[_EnvType, _NewValueType, _ErrorType], -]: - ... - - -@overload -def _bind( - function: Callable[ - [_ValueType], - RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType], - ], -) -> Callable[ - [RequiresContextFutureResult[_EnvType, _ValueType, _ErrorType]], - RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType], -]: - ... - - -@overload -def _bind( - function: Callable[[_ValueType], Result[_NewValueType, _ErrorType]], -) -> Callable[ - [Result[_ValueType, _ErrorType]], - Result[_NewValueType, _ErrorType], -]: - ... - - -@overload -def _bind( - function: Callable[[_ValueType], IOResult[_NewValueType, _ErrorType]], -) -> Callable[ - [IOResult[_ValueType, _ErrorType]], - IOResult[_NewValueType, _ErrorType], -]: - ... - - -@overload -def _bind( - function: Callable[[_ValueType], Future[_NewValueType]], -) -> Callable[[Future[_ValueType]], Future[_NewValueType]]: - ... - - -@overload -def _bind( - function: Callable[[_ValueType], FutureResult[_NewValueType, _ErrorType]], -) -> Callable[ - [FutureResult[_ValueType, _ErrorType]], - FutureResult[_NewValueType, _ErrorType], -]: - ... diff --git a/returns/_generated/pointfree/bind_async.py b/returns/_generated/pointfree/bind_async.py deleted file mode 100644 index 0be8e8c51..000000000 --- a/returns/_generated/pointfree/bind_async.py +++ /dev/null @@ -1,25 +0,0 @@ -def _bind_async(function): - """ - Compose a container and ``async`` function returning a container. - - In other words, it modifies the function's - signature from: ``a -> Awaitable[Container[b]]`` - to: ``Container[a] -> Container[b]`` - - This is how it should be used: - - .. code:: python - - >>> import anyio - >>> from returns.future import Future - >>> from returns.io import IO - >>> from returns.pointfree import bind_async - - >>> async def coroutine(x: int) -> Future[str]: - ... return Future.from_value(str(x + 1)) - - >>> bound = bind_async(coroutine)(Future.from_value(1)) - >>> assert anyio.run(bound.awaitable) == IO('2') - - """ - return lambda container: container.bind_async(function) diff --git a/returns/_generated/pointfree/bind_async.pyi b/returns/_generated/pointfree/bind_async.pyi deleted file mode 100644 index 4ebc72b28..000000000 --- a/returns/_generated/pointfree/bind_async.pyi +++ /dev/null @@ -1,44 +0,0 @@ -from typing import Awaitable, Callable, TypeVar, overload - -from returns.context import RequiresContextFutureResult -from returns.future import Future, FutureResult - -_ValueType = TypeVar('_ValueType', contravariant=True) -_ErrorType = TypeVar('_ErrorType') -_NewValueType = TypeVar('_NewValueType', covariant=True) -_EnvType = TypeVar('_EnvType') - - -@overload -def _bind_async( - function: Callable[[_ValueType], Awaitable[Future[_NewValueType]]], -) -> Callable[[Future[_ValueType]], Future[_NewValueType]]: - ... - - -@overload -def _bind_async( - function: Callable[ - [_ValueType], - Awaitable[FutureResult[_NewValueType, _ErrorType]], - ], -) -> Callable[ - [FutureResult[_ValueType, _ErrorType]], - FutureResult[_NewValueType, _ErrorType], -]: - ... - - -@overload -def _bind_async( - function: Callable[ - [_ValueType], - Awaitable[RequiresContextFutureResult[ - _EnvType, _NewValueType, _ErrorType, - ]], - ], -) -> Callable[ - [RequiresContextFutureResult[_EnvType, _ValueType, _ErrorType]], - RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType], -]: - ... diff --git a/returns/_generated/pointfree/bind_async_future.py b/returns/_generated/pointfree/bind_async_future.py deleted file mode 100644 index 006e029e5..000000000 --- a/returns/_generated/pointfree/bind_async_future.py +++ /dev/null @@ -1,28 +0,0 @@ -def _bind_async_future(function): - """ - Compose a container and ``async`` function returning a `container`. - - In other words, it modifies the function's - signature from: ``a -> Awaitable[Container[b]]`` - to: ``Container[a] -> Container[b]`` - - This is how it should be used: - - .. code:: python - - >>> import anyio - >>> from returns.future import Future, FutureResult - >>> from returns.io import IOSuccess, IOFailure - >>> from returns.pointfree import bind_async_future - - >>> async def coroutine(x: int) -> Future[str]: - ... return Future.from_value(str(x + 1)) - - >>> bound = bind_async_future(coroutine)(FutureResult.from_value(1)) - >>> assert anyio.run(bound.awaitable) == IOSuccess('2') - - >>> bound = bind_async_future(coroutine)(FutureResult.from_failure(1)) - >>> assert anyio.run(bound.awaitable) == IOFailure(1) - - """ - return lambda container: container.bind_async_future(function) diff --git a/returns/_generated/pointfree/bind_async_future.pyi b/returns/_generated/pointfree/bind_async_future.pyi deleted file mode 100644 index b0666d367..000000000 --- a/returns/_generated/pointfree/bind_async_future.pyi +++ /dev/null @@ -1,44 +0,0 @@ -from typing import Awaitable, Callable, TypeVar, overload - -from typing_extensions import Protocol - -from returns.context import RequiresContextFutureResult -from returns.future import Future, FutureResult - -_ValueType = TypeVar('_ValueType', contravariant=True) -_ErrorType = TypeVar('_ErrorType') -_NewValueType = TypeVar('_NewValueType', covariant=True) -_EnvType = TypeVar('_EnvType') - - -class _BindAsyncFuture(Protocol[_ValueType, _NewValueType]): - """ - Helper class to represent type overloads for ret_type based on a value type. - - Contains all containers we have. - - It does not exist in runtime. - It is also completely removed from typing with the help of the mypy plugin. - """ - - @overload - def __call__( - self, - container: FutureResult[_ValueType, _ErrorType], - ) -> FutureResult[_NewValueType, _ErrorType]: - ... - - @overload - def __call__( - self, - container: RequiresContextFutureResult[ - _EnvType, _ValueType, _ErrorType, - ], - ) -> RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType]: - ... - - -def _bind_async_future( - function: Callable[[_ValueType], Awaitable[Future[_NewValueType]]], -) -> _BindAsyncFuture[_ValueType, _NewValueType]: - ... diff --git a/returns/_generated/pointfree/bind_async_future_result.py b/returns/_generated/pointfree/bind_async_future_result.py deleted file mode 100644 index 30d037fbd..000000000 --- a/returns/_generated/pointfree/bind_async_future_result.py +++ /dev/null @@ -1,33 +0,0 @@ -def _bind_async_future_result(function): - """ - Compose a container and ``async`` function returning a ``FutureResult``. - - In other words, it modifies the function's - signature from: ``a -> Awaitable[FutureResult[b, c]]`` - to: ``Container[a, c] -> Container[b, c]`` - - This is how it should be used: - - .. code:: python - - >>> import anyio - >>> from returns.future import FutureResult - >>> from returns.context import ReaderFutureResult - >>> from returns.io import IOSuccess, IOFailure - >>> from returns.pointfree import bind_async_future_result - - >>> async def coroutine(x: int) -> FutureResult[str, int]: - ... return FutureResult.from_value(str(x + 1)) - - >>> bound = bind_async_future_result(coroutine)( - ... ReaderFutureResult.from_value(1), - ... ) - >>> assert anyio.run(bound, ReaderFutureResult.empty) == IOSuccess('2') - - >>> bound = bind_async_future_result(coroutine)( - ... ReaderFutureResult.from_failure(1), - ... ) - >>> assert anyio.run(bound, ReaderFutureResult.empty) == IOFailure(1) - - """ - return lambda container: container.bind_async_future_result(function) diff --git a/returns/_generated/pointfree/bind_async_future_result.pyi b/returns/_generated/pointfree/bind_async_future_result.pyi deleted file mode 100644 index 2de876d7d..000000000 --- a/returns/_generated/pointfree/bind_async_future_result.pyi +++ /dev/null @@ -1,39 +0,0 @@ -from typing import Awaitable, Callable, TypeVar - -from typing_extensions import Protocol - -from returns.context import RequiresContextFutureResult -from returns.future import FutureResult - -_ValueType = TypeVar('_ValueType', contravariant=True) -_ErrorType = TypeVar('_ErrorType') -_NewValueType = TypeVar('_NewValueType', covariant=True) -_EnvType = TypeVar('_EnvType') - - -class _BindAsyncFutureResult(Protocol[_ValueType, _NewValueType, _ErrorType]): - """ - Helper class to represent type overloads for ret_type based on a value type. - - Contains all containers we have. - - It does not exist in runtime. - It is also completely removed from typing with the help of the mypy plugin. - """ - - def __call__( - self, - container: RequiresContextFutureResult[ - _EnvType, _ValueType, _ErrorType, - ], - ) -> RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType]: - ... - - -def _bind_async_future_result( - function: Callable[ - [_ValueType], - Awaitable[FutureResult[_NewValueType, _ErrorType]], - ], -) -> _BindAsyncFutureResult[_ValueType, _NewValueType, _ErrorType]: - ... diff --git a/returns/_generated/pointfree/bind_awaitable.py b/returns/_generated/pointfree/bind_awaitable.py deleted file mode 100644 index 351b9b637..000000000 --- a/returns/_generated/pointfree/bind_awaitable.py +++ /dev/null @@ -1,26 +0,0 @@ -def _bind_awaitable(function): - """ - Composes a container a regular ``async`` function. - - This function should return plain, non-container value. - - In other words, it modifies the function's - signature from: ``a -> Awaitable[b]`` - to: ``Container[a] -> Container[b]`` - - .. code:: python - - >>> import anyio - >>> from returns.future import Future - >>> from returns.io import IO - >>> from returns.pointfree import bind_awaitable - - >>> async def coroutine(x: int) -> int: - ... return x + 1 - - >>> assert anyio.run( - ... bind_awaitable(coroutine)(Future.from_value(1)).awaitable, - ... ) == IO(2) - - """ - return lambda container: container.bind_awaitable(function) diff --git a/returns/_generated/pointfree/bind_awaitable.pyi b/returns/_generated/pointfree/bind_awaitable.pyi deleted file mode 100644 index fec616589..000000000 --- a/returns/_generated/pointfree/bind_awaitable.pyi +++ /dev/null @@ -1,51 +0,0 @@ -from typing import Awaitable, Callable, TypeVar, overload - -from typing_extensions import Protocol - -from returns.context import RequiresContextFutureResult -from returns.future import Future, FutureResult - -_ValueType = TypeVar('_ValueType', contravariant=True) -_ErrorType = TypeVar('_ErrorType') -_NewValueType = TypeVar('_NewValueType', covariant=True) -_EnvType = TypeVar('_EnvType') - - -class _BindAwaitable(Protocol[_ValueType, _NewValueType]): - """ - Helper class to represent type overloads for ret_type based on a value type. - - Contains all containers we have. - - It does not exist in runtime. - It is also completely removed from typing with the help of the mypy plugin. - """ - - @overload - def __call__( - self, - container: Future[_ValueType], - ) -> Future[_NewValueType]: - ... - - @overload - def __call__( - self, - container: FutureResult[_ValueType, _ErrorType], - ) -> FutureResult[_NewValueType, _ErrorType]: - ... - - @overload - def __call__( - self, - container: RequiresContextFutureResult[ - _EnvType, _ValueType, _ErrorType, - ], - ) -> RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType]: - ... - - -def _bind_awaitable( - function: Callable[[_ValueType], Awaitable[_NewValueType]], -) -> _BindAwaitable[_ValueType, _NewValueType]: - ... diff --git a/returns/_generated/pointfree/bind_context.py b/returns/_generated/pointfree/bind_context.py deleted file mode 100644 index 93059457f..000000000 --- a/returns/_generated/pointfree/bind_context.py +++ /dev/null @@ -1,27 +0,0 @@ -def _bind_context(function): - """ - Lifts function from ``RequiresContext`` for better composition. - - In other words, it modifies the function's - signature from: ``a -> RequiresContext[env, b]`` to: - ``Container[env, a, c]`` -> ``Container[env, b, c]`` - - .. code:: python - - >>> from returns.context import RequiresContext, RequiresContextResult - >>> from returns.result import Success, Failure - >>> from returns.pointfree import bind_context - - >>> def function(arg: int) -> RequiresContext[str, int]: - ... return RequiresContext(lambda deps: len(deps) + arg) - - >>> assert bind_context(function)( - ... RequiresContextResult.from_value(2), - ... )('abc') == Success(5) - - >>> assert bind_context(function)( - ... RequiresContextResult.from_failure(0), - ... )('abc') == Failure(0) - - """ - return lambda container: container.bind_context(function) diff --git a/returns/_generated/pointfree/bind_context.pyi b/returns/_generated/pointfree/bind_context.pyi deleted file mode 100644 index c3bb5ebb3..000000000 --- a/returns/_generated/pointfree/bind_context.pyi +++ /dev/null @@ -1,55 +0,0 @@ -from typing import Callable, TypeVar, overload - -from typing_extensions import Protocol - -from returns.context import ( - RequiresContext, - RequiresContextFutureResult, - RequiresContextIOResult, - RequiresContextResult, -) - -_ValueType = TypeVar('_ValueType', contravariant=True) -_ErrorType = TypeVar('_ErrorType') -_NewValueType = TypeVar('_NewValueType', covariant=True) -_EnvType = TypeVar('_EnvType') - - -class _BindContext(Protocol[_EnvType, _ValueType, _NewValueType]): - """ - Helper class to represent type overloads for ret_type based on a value type. - - Contains all containers we have. - - It does not exist in runtime. - It is also completely removed from typing with the help of the mypy plugin. - """ - - @overload - def __call__( - self, - container: RequiresContextResult[_EnvType, _ValueType, _ErrorType], - ) -> RequiresContextResult[_EnvType, _NewValueType, _ErrorType]: - ... - - @overload - def __call__( - self, - container: RequiresContextIOResult[_EnvType, _ValueType, _ErrorType], - ) -> RequiresContextIOResult[_EnvType, _NewValueType, _ErrorType]: - ... - - @overload - def __call__( - self, - container: RequiresContextFutureResult[ - _EnvType, _ValueType, _ErrorType, - ], - ) -> RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType]: - ... - - -def _bind_context( - function: Callable[[_ValueType], RequiresContext[_EnvType, _NewValueType]], -) -> _BindContext[_EnvType, _ValueType, _NewValueType]: - ... diff --git a/returns/_generated/pointfree/bind_context_ioresult.py b/returns/_generated/pointfree/bind_context_ioresult.py deleted file mode 100644 index 4e03df9bf..000000000 --- a/returns/_generated/pointfree/bind_context_ioresult.py +++ /dev/null @@ -1,33 +0,0 @@ -def _bind_context_ioresult(function): - """ - Lifts function from ``RequiresContextIOResult`` for better composition. - - In other words, it modifies the function's - signature from: ``a -> RequiresContextResult[env, b, c]`` to: - ``Container[env, a, c]`` -> ``Container[env, b, c]`` - - .. code:: python - - >>> import anyio - >>> from returns.context import ( - ... RequiresContextFutureResult, - ... RequiresContextIOResult, - ... ) - >>> from returns.io import IOSuccess, IOFailure - >>> from returns.pointfree import bind_context_ioresult - - >>> def function(arg: int) -> RequiresContextIOResult[str, int, str]: - ... return RequiresContextIOResult( - ... lambda deps: IOSuccess(len(deps) + arg), - ... ) - - >>> assert anyio.run(bind_context_ioresult(function)( - ... RequiresContextFutureResult.from_value(2), - ... )('abc').awaitable) == IOSuccess(5) - - >>> assert anyio.run(bind_context_ioresult(function)( - ... RequiresContextFutureResult.from_failure(0), - ... )('abc').awaitable) == IOFailure(0) - - """ - return lambda container: container.bind_context_ioresult(function) diff --git a/returns/_generated/pointfree/bind_context_ioresult.pyi b/returns/_generated/pointfree/bind_context_ioresult.pyi deleted file mode 100644 index aefca9613..000000000 --- a/returns/_generated/pointfree/bind_context_ioresult.pyi +++ /dev/null @@ -1,40 +0,0 @@ -from typing import Callable, TypeVar - -from typing_extensions import Protocol - -from returns.context import RequiresContextFutureResult, RequiresContextIOResult - -_ValueType = TypeVar('_ValueType', contravariant=True) -_ErrorType = TypeVar('_ErrorType') -_NewValueType = TypeVar('_NewValueType', covariant=True) -_EnvType = TypeVar('_EnvType') - - -class _BindContextIOResult( - Protocol[_EnvType, _ValueType, _NewValueType, _ErrorType], -): - """ - Helper class to represent type overloads for ret_type based on a value type. - - Contains all containers we have. - - It does not exist in runtime. - It is also completely removed from typing with the help of the mypy plugin. - """ - - def __call__( - self, - container: RequiresContextFutureResult[ - _EnvType, _ValueType, _ErrorType, - ], - ) -> RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType]: - ... - - -def _bind_context_ioresult( - function: Callable[ - [_ValueType], - RequiresContextIOResult[_EnvType, _NewValueType, _ErrorType], - ], -) -> _BindContextIOResult[_EnvType, _ValueType, _NewValueType, _ErrorType]: - ... diff --git a/returns/_generated/pointfree/bind_context_result.py b/returns/_generated/pointfree/bind_context_result.py deleted file mode 100644 index 4ab3a278a..000000000 --- a/returns/_generated/pointfree/bind_context_result.py +++ /dev/null @@ -1,33 +0,0 @@ -def _bind_context_result(function): - """ - Lifts function from ``RequiresContextResult`` for better composition. - - In other words, it modifies the function's - signature from: ``a -> RequiresContextResult[env, b, c]`` to: - ``Container[env, a, c]`` -> ``Container[env, b, c]`` - - .. code:: python - - >>> from returns.context import ( - ... RequiresContextResult, - ... RequiresContextIOResult, - ... ) - >>> from returns.io import IOSuccess, IOFailure - >>> from returns.result import Success - >>> from returns.pointfree import bind_context_result - - >>> def function(arg: int) -> RequiresContextResult[str, int, str]: - ... return RequiresContextResult( - ... lambda deps: Success(len(deps) + arg), - ... ) - - >>> assert bind_context_result(function)( - ... RequiresContextIOResult.from_value(2), - ... )('abc') == IOSuccess(5) - - >>> assert bind_context_result(function)( - ... RequiresContextIOResult.from_failure(0), - ... )('abc') == IOFailure(0) - - """ - return lambda container: container.bind_context_result(function) diff --git a/returns/_generated/pointfree/bind_context_result.pyi b/returns/_generated/pointfree/bind_context_result.pyi deleted file mode 100644 index 3da38c235..000000000 --- a/returns/_generated/pointfree/bind_context_result.pyi +++ /dev/null @@ -1,52 +0,0 @@ -from typing import Callable, TypeVar, overload - -from typing_extensions import Protocol - -from returns.context import ( - RequiresContextFutureResult, - RequiresContextIOResult, - RequiresContextResult, -) - -_ValueType = TypeVar('_ValueType', contravariant=True) -_ErrorType = TypeVar('_ErrorType') -_NewValueType = TypeVar('_NewValueType', covariant=True) -_EnvType = TypeVar('_EnvType') - - -class _BindContextResult( - Protocol[_EnvType, _ValueType, _NewValueType, _ErrorType], -): - """ - Helper class to represent type overloads for ret_type based on a value type. - - Contains all containers we have. - - It does not exist in runtime. - It is also completely removed from typing with the help of the mypy plugin. - """ - - @overload - def __call__( - self, - container: RequiresContextIOResult[_EnvType, _ValueType, _ErrorType], - ) -> RequiresContextIOResult[_EnvType, _NewValueType, _ErrorType]: - ... - - @overload - def __call__( - self, - container: RequiresContextFutureResult[ - _EnvType, _ValueType, _ErrorType, - ], - ) -> RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType]: - ... - - -def _bind_context_result( - function: Callable[ - [_ValueType], - RequiresContextResult[_EnvType, _NewValueType, _ErrorType], - ], -) -> _BindContextResult[_EnvType, _ValueType, _NewValueType, _ErrorType]: - ... diff --git a/returns/_generated/pointfree/bind_future.py b/returns/_generated/pointfree/bind_future.py deleted file mode 100644 index b0031509f..000000000 --- a/returns/_generated/pointfree/bind_future.py +++ /dev/null @@ -1,33 +0,0 @@ -def _bind_future(function): - """ - Lifts ``Future`` function to be wrapped in other container. - - In other words, it modifies the function's - signature from: ``a -> Future[b]`` - to: ``Container[a] -> Container[b]`` - - This is how it should be used: - - .. code:: python - - >>> import anyio - >>> from returns.future import Future, FutureResult - >>> from returns.io import IOSuccess, IOFailure - >>> from returns.pointfree import bind_future - - >>> def example(argument: int) -> Future[float]: - ... return Future.from_value(argument / 2) - - >>> async def success() -> FutureResult[float, int]: - ... container = FutureResult.from_value(1) - ... return await bind_future(example)(container) - - >>> async def failure() -> FutureResult[float, int]: - ... container = FutureResult.from_failure(1) - ... return await bind_future(example)(container) - - >>> assert anyio.run(success) == IOSuccess(0.5) - >>> assert anyio.run(failure) == IOFailure(1) - - """ - return lambda container: container.bind_future(function) diff --git a/returns/_generated/pointfree/bind_future.pyi b/returns/_generated/pointfree/bind_future.pyi deleted file mode 100644 index 8d37eec97..000000000 --- a/returns/_generated/pointfree/bind_future.pyi +++ /dev/null @@ -1,44 +0,0 @@ -from typing import Callable, TypeVar, overload - -from typing_extensions import Protocol - -from returns.context import RequiresContextFutureResult -from returns.future import Future, FutureResult - -_ValueType = TypeVar('_ValueType', contravariant=True) -_ErrorType = TypeVar('_ErrorType') -_NewValueType = TypeVar('_NewValueType', covariant=True) -_EnvType = TypeVar('_EnvType') - - -class _BindFuture(Protocol[_ValueType, _NewValueType]): - """ - Helper class to represent type overloads for ret_type based on a value type. - - Contains all containers we have. - - It does not exist in runtime. - It is also completely removed from typing with the help of the mypy plugin. - """ - - @overload - def __call__( - self, - container: FutureResult[_ValueType, _ErrorType], - ) -> FutureResult[_NewValueType, _ErrorType]: - ... - - @overload - def __call__( - self, - container: RequiresContextFutureResult[ - _EnvType, _ValueType, _ErrorType, - ], - ) -> RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType]: - ... - - -def _bind_future( - function: Callable[[_ValueType], Future[_NewValueType]], -) -> _BindFuture[_ValueType, _NewValueType]: - ... diff --git a/returns/_generated/pointfree/bind_future_result.py b/returns/_generated/pointfree/bind_future_result.py deleted file mode 100644 index 9f1db2130..000000000 --- a/returns/_generated/pointfree/bind_future_result.py +++ /dev/null @@ -1,31 +0,0 @@ -def _bind_future_result(function): - """ - Lifts ``FutureResult`` function to be wrapped in other container. - - In other words, it modifies the function's - signature from: ``a -> FutureResult[b, c]`` - to: ``Container[a, c] -> Container[b, c]`` - - This is how it should be used: - - .. code:: python - - >>> import anyio - >>> from returns.future import FutureResultE - >>> from returns.context import ReaderFutureResultE - >>> from returns.io import IOSuccess, IOFailure - >>> from returns.pointfree import bind_future_result - - >>> def example(argument: int) -> FutureResultE[float]: - ... return FutureResultE.from_value(argument / 2) - - >>> assert anyio.run(bind_future_result(example)( - ... ReaderFutureResultE.from_value(1), - ... ), ReaderFutureResultE.empty) == IOSuccess(0.5) - - >>> assert anyio.run(bind_future_result(example)( - ... ReaderFutureResultE.from_failure(':('), - ... ), ReaderFutureResultE.empty) == IOFailure(':(') - - """ - return lambda container: container.bind_future_result(function) diff --git a/returns/_generated/pointfree/bind_future_result.pyi b/returns/_generated/pointfree/bind_future_result.pyi deleted file mode 100644 index dd83c4e95..000000000 --- a/returns/_generated/pointfree/bind_future_result.pyi +++ /dev/null @@ -1,36 +0,0 @@ -from typing import Callable, TypeVar - -from typing_extensions import Protocol - -from returns.context import RequiresContextFutureResult -from returns.future import FutureResult - -_ValueType = TypeVar('_ValueType', contravariant=True) -_ErrorType = TypeVar('_ErrorType') -_NewValueType = TypeVar('_NewValueType', covariant=True) -_EnvType = TypeVar('_EnvType') - - -class _BindFutureResult(Protocol[_ValueType, _NewValueType, _ErrorType]): - """ - Helper class to represent type overloads for ret_type based on a value type. - - Contains all containers we have. - - It does not exist in runtime. - It is also completely removed from typing with the help of the mypy plugin. - """ - - def __call__( - self, - container: RequiresContextFutureResult[ - _EnvType, _ValueType, _ErrorType, - ], - ) -> RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType]: - ... - - -def _bind_future_result( - function: Callable[[_ValueType], FutureResult[_NewValueType, _ErrorType]], -) -> _BindFutureResult[_ValueType, _NewValueType, _ErrorType]: - ... diff --git a/returns/_generated/pointfree/bind_io.py b/returns/_generated/pointfree/bind_io.py deleted file mode 100644 index c29a5a09d..000000000 --- a/returns/_generated/pointfree/bind_io.py +++ /dev/null @@ -1,40 +0,0 @@ -def _bind_io(function): - """ - Lifts ``IO`` function to be wrapped in other container. - - In other words, it modifies the function's - signature from: ``a -> IO[b]`` to: ``Container[a] -> Container[b]`` - - This is how it should be used: - - .. code:: python - - >>> import anyio - >>> from returns.future import Future - >>> from returns.io import IO - >>> from returns.pointfree import bind_io - - >>> def example(argument: int) -> IO[float]: - ... return IO(argument / 2) - - >>> async def main() -> Future[float]: - ... container = Future.from_value(1) - ... return await bind_io(example)(container) - - >>> assert anyio.run(main) == IO(0.5) - - Or with sync code: - - .. code:: python - - >>> from returns.io import IO, IOSuccess, IOFailure - - >>> def returns_io(arg: int) -> IO[float]: - ... return IO(arg + 0.5) - - >>> bound = bind_io(returns_io) - >>> assert bound(IOSuccess(1)) == IOSuccess(1.5) - >>> assert bound(IOFailure(1)) == IOFailure(1) - - """ - return lambda container: container.bind_io(function) diff --git a/returns/_generated/pointfree/bind_io.pyi b/returns/_generated/pointfree/bind_io.pyi deleted file mode 100644 index 192094dd7..000000000 --- a/returns/_generated/pointfree/bind_io.pyi +++ /dev/null @@ -1,66 +0,0 @@ -from typing import Callable, TypeVar, overload - -from typing_extensions import Protocol - -from returns.context import RequiresContextFutureResult, RequiresContextIOResult -from returns.future import Future, FutureResult -from returns.io import IO, IOResult - -_ValueType = TypeVar('_ValueType', contravariant=True) -_ErrorType = TypeVar('_ErrorType') -_NewValueType = TypeVar('_NewValueType', covariant=True) -_EnvType = TypeVar('_EnvType', contravariant=True) - - -class _BindIO(Protocol[_ValueType, _NewValueType]): - """ - Helper class to represent type overloads for ret_type based on a value type. - - Contains all containers we have. - - It does not exist in runtime. - It is also completely removed from typing with the help of the mypy plugin. - """ - - @overload - def __call__( - self, - container: RequiresContextIOResult[_EnvType, _ValueType, _ErrorType], - ) -> RequiresContextIOResult[_EnvType, _NewValueType, _ErrorType]: - ... - - @overload - def __call__( - self, - container: RequiresContextFutureResult[ - _EnvType, _ValueType, _ErrorType, - ], - ) -> RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType]: - ... - - @overload - def __call__( - self, - container: IOResult[_ValueType, _ErrorType], - ) -> IOResult[_NewValueType, _ErrorType]: - ... - - @overload - def __call__( - self, - container: Future[_ValueType], - ) -> Future[_NewValueType]: - ... - - @overload - def __call__( - self, - container: FutureResult[_ValueType, _ErrorType], - ) -> FutureResult[_NewValueType, _ErrorType]: - ... - - -def _bind_io( - function: Callable[[_ValueType], IO[_NewValueType]], -) -> _BindIO[_ValueType, _NewValueType]: - ... diff --git a/returns/_generated/pointfree/bind_ioresult.py b/returns/_generated/pointfree/bind_ioresult.py deleted file mode 100644 index 7747c6d43..000000000 --- a/returns/_generated/pointfree/bind_ioresult.py +++ /dev/null @@ -1,58 +0,0 @@ -def _bind_ioresult(function): - """ - Lifts function returning ``IOResult`` to be wrapped in another container. - - In other words, it modifies the function's - signature from: ``a -> IOResult[b, c]`` - to: ``Container[a, c] -> Container[b, c]`` - - This is how it should be used: - - .. code:: python - - >>> import anyio - >>> from returns.future import FutureResult - >>> from returns.io import IOSuccess, IOFailure, IOResult - >>> from returns.pointfree import bind_ioresult - - >>> def example(argument: int) -> IOResult[float, int]: - ... return IOSuccess(argument / 2) - - >>> async def success() -> FutureResult[float, int]: - ... container = FutureResult.from_value(1) - ... return await bind_ioresult(example)(container) - - >>> async def failure() -> FutureResult[float, int]: - ... container = FutureResult.from_failure(1) - ... return await bind_ioresult(example)(container) - - >>> assert anyio.run(success) == IOSuccess(0.5) - >>> assert anyio.run(failure) == IOFailure(1) - - And with sync code: - - .. code:: python - - >>> from returns.context import RequiresContextIOResult - - >>> def function(arg: int) -> IOResult[str, int]: - ... if arg > 0: - ... return IOSuccess(str(arg) + '!') - ... return IOFailure(arg) - - >>> deps = RequiresContextIOResult.empty - - >>> assert bind_ioresult(function)( - ... RequiresContextIOResult.from_value(1), - ... )(deps) == IOSuccess('1!') - - >>> assert bind_ioresult(function)( - ... RequiresContextIOResult.from_value(0), - ... )(deps) == IOFailure(0) - - >>> assert bind_ioresult(function)( - ... RequiresContextIOResult.from_failure('nope'), - ... )(deps) == IOFailure('nope') - - """ - return lambda container: container.bind_ioresult(function) diff --git a/returns/_generated/pointfree/bind_ioresult.pyi b/returns/_generated/pointfree/bind_ioresult.pyi deleted file mode 100644 index c38814432..000000000 --- a/returns/_generated/pointfree/bind_ioresult.pyi +++ /dev/null @@ -1,52 +0,0 @@ -from typing import Callable, TypeVar, overload - -from typing_extensions import Protocol - -from returns.context import RequiresContextFutureResult, RequiresContextIOResult -from returns.future import FutureResult -from returns.io import IOResult - -_ValueType = TypeVar('_ValueType', contravariant=True) -_ErrorType = TypeVar('_ErrorType') -_NewValueType = TypeVar('_NewValueType', covariant=True) -_EnvType = TypeVar('_EnvType', contravariant=True) - - -class _BindIOResult(Protocol[_ValueType, _NewValueType, _ErrorType]): - """ - Helper class to represent type overloads for ret_type based on a value type. - - Contains all containers we have. - - It does not exist in runtime. - It is also completely removed from typing with the help of the mypy plugin. - """ - - @overload - def __call__( - self, - container: RequiresContextIOResult[_EnvType, _ValueType, _ErrorType], - ) -> RequiresContextIOResult[_EnvType, _NewValueType, _ErrorType]: - ... - - @overload - def __call__( - self, - container: RequiresContextFutureResult[ - _EnvType, _ValueType, _ErrorType, - ], - ) -> RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType]: - ... - - @overload - def __call__( - self, - container: FutureResult[_ValueType, _ErrorType], - ) -> FutureResult[_NewValueType, _ErrorType]: - ... - - -def _bind_ioresult( - function: Callable[[_ValueType], IOResult[_NewValueType, _ErrorType]], -) -> _BindIOResult[_ValueType, _NewValueType, _ErrorType]: - ... diff --git a/returns/_generated/pointfree/bind_result.py b/returns/_generated/pointfree/bind_result.py deleted file mode 100644 index 72a2479bc..000000000 --- a/returns/_generated/pointfree/bind_result.py +++ /dev/null @@ -1,24 +0,0 @@ -def _bind_result(function): - """ - Composes successful container with a function that returns a container. - - In other words, it modifies the function's - signature from: ``a -> Result[b, c]`` - to: ``Container[a, c] -> Container[b, c]`` - - .. code:: python - - >>> from returns.io import IOSuccess - >>> from returns.context import RequiresContextResult - >>> from returns.result import Result, Success - >>> from returns.pointfree import bind_result - - >>> def returns_result(arg: int) -> Result[int, str]: - ... return Success(arg + 1) - - >>> bound = bind_result(returns_result) - >>> assert bound(IOSuccess(1)) == IOSuccess(2) - >>> assert bound(RequiresContextResult.from_value(1))(...) == Success(2) - - """ - return lambda container: container.bind_result(function) diff --git a/returns/_generated/pointfree/bind_result.pyi b/returns/_generated/pointfree/bind_result.pyi deleted file mode 100644 index 49b522ae1..000000000 --- a/returns/_generated/pointfree/bind_result.pyi +++ /dev/null @@ -1,71 +0,0 @@ -from typing import Callable, TypeVar, overload - -from typing_extensions import Protocol - -from returns.context import ( - RequiresContextFutureResult, - RequiresContextIOResult, - RequiresContextResult, -) -from returns.future import FutureResult -from returns.io import IOResult -from returns.result import Result - -_ValueType = TypeVar('_ValueType', contravariant=True) -_ErrorType = TypeVar('_ErrorType') -_NewValueType = TypeVar('_NewValueType', covariant=True) -_EnvType = TypeVar('_EnvType', contravariant=True) - - -class _BindResult(Protocol[_ValueType, _NewValueType, _ErrorType]): - """ - Helper class to represent type overloads for ret_type based on a value type. - - Contains all containers we have. - - It does not exist in runtime. - It is also completely removed from typing with the help of the mypy plugin. - """ - - @overload - def __call__( - self, - container: RequiresContextResult[_EnvType, _ValueType, _ErrorType], - ) -> RequiresContextResult[_EnvType, _NewValueType, _ErrorType]: - ... - - @overload - def __call__( - self, - container: RequiresContextIOResult[_EnvType, _ValueType, _ErrorType], - ) -> RequiresContextIOResult[_EnvType, _NewValueType, _ErrorType]: - ... - - @overload - def __call__( - self, - container: RequiresContextFutureResult[ - _EnvType, _ValueType, _ErrorType, - ], - ) -> RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType]: - ... - - @overload - def __call__( - self, - container: IOResult[_ValueType, _ErrorType], - ) -> IOResult[_NewValueType, _ErrorType]: - ... - - @overload - def __call__( - self, - container: FutureResult[_ValueType, _ErrorType], - ) -> FutureResult[_NewValueType, _ErrorType]: - ... - - -def _bind_result( - function: Callable[[_ValueType], Result[_NewValueType, _ErrorType]], -) -> _BindResult[_ValueType, _NewValueType, _ErrorType]: - ... diff --git a/returns/_generated/pointfree/fix.py b/returns/_generated/pointfree/fix.py deleted file mode 100644 index e0f268e7f..000000000 --- a/returns/_generated/pointfree/fix.py +++ /dev/null @@ -1,28 +0,0 @@ -def _fix(function): - """ - Lifts function to be wrapped in a container for better composition. - - In other words, it modifies the function's - signature from: ``a -> b`` to: ``Container[a] -> Container[b]`` - - Works similar to :meth:`returns.primitives.interfaces.Fixable.fix`, - but has inverse semantics. - - This is how it should be used: - - .. code:: python - - >>> from returns.result import Result, Success, Failure - >>> from returns.pointfree import fix - - >>> def example(argument: int) -> float: - ... return argument / 2 - - >>> first: Result[int, int] = Success(1) - >>> second: Result[int, int] = Failure(1) - - >>> assert fix(example)(first) == Success(1) - >>> assert fix(example)(second) == Success(0.5) - - """ - return lambda container: container.fix(function) diff --git a/returns/_generated/pointfree/fix.pyi b/returns/_generated/pointfree/fix.pyi deleted file mode 100644 index 17e0fd25e..000000000 --- a/returns/_generated/pointfree/fix.pyi +++ /dev/null @@ -1,78 +0,0 @@ -from typing import Callable, TypeVar, overload - -from typing_extensions import Protocol - -from returns.context import ( - RequiresContextFutureResult, - RequiresContextIOResult, - RequiresContextResult, -) -from returns.future import FutureResult -from returns.io import IOResult -from returns.result import Result - -_ValueType = TypeVar('_ValueType') -_ErrorType = TypeVar('_ErrorType') -_NewValueType = TypeVar('_NewValueType', covariant=True) -_EnvType = TypeVar('_EnvType', contravariant=True) - - -class _Fixable(Protocol[_ErrorType, _NewValueType]): - """ - Represents type overloads for ``ret_type`` based on an error type. - - Contains all containers we have. - - It does not exist in runtime. - It is also completely removed from typing with the help of the mypy plugin. - """ - - @overload - def __call__( - self, - container: RequiresContextResult[_EnvType, _ValueType, _ErrorType], - ) -> RequiresContextResult[_EnvType, _NewValueType, _ErrorType]: - ... - - @overload - def __call__( - self, - container: RequiresContextIOResult[_EnvType, _ValueType, _ErrorType], - ) -> RequiresContextIOResult[_EnvType, _NewValueType, _ErrorType]: - ... - - @overload - def __call__( - self, - container: RequiresContextFutureResult[ - _EnvType, _ValueType, _ErrorType, - ], - ) -> RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType]: - ... - - @overload - def __call__( - self, - container: Result[_ValueType, _ErrorType], - ) -> Result[_NewValueType, _ErrorType]: - ... - - @overload - def __call__( - self, - container: IOResult[_ValueType, _ErrorType], - ) -> IOResult[_NewValueType, _ErrorType]: - ... - - @overload - def __call__( - self, - container: FutureResult[_ValueType, _ErrorType], - ) -> FutureResult[_NewValueType, _ErrorType]: - ... - - -def _fix( - function: Callable[[_ErrorType], _NewValueType], -) -> _Fixable[_ErrorType, _NewValueType]: - ... diff --git a/returns/_generated/pointfree/map.py b/returns/_generated/pointfree/map.py deleted file mode 100644 index c79eb198c..000000000 --- a/returns/_generated/pointfree/map.py +++ /dev/null @@ -1,32 +0,0 @@ -def _map(function): - """ - Lifts function to be wrapped in a container for better composition. - - In other words, it modifies the function's - signature from: ``a -> b`` to: ``Container[a] -> Container[b]`` - - Works similar to :meth:`returns.primitives.interfaces.Mappable.map`, - but has inverse semantics. - - This is how it should be used: - - .. code:: python - - >>> import anyio - >>> from returns.future import Future - >>> from returns.io import IO - >>> from returns.pointfree import map_ - - >>> def example(argument: int) -> float: - ... return argument / 2 # not a container! - - >>> async def main() -> Future[float]: - ... return await map_(example)(Future.from_value(1)) - - >>> assert anyio.run(main) == IO(0.5) - - See also: - - https://wiki.haskell.org/Lifting - - """ - return lambda container: container.map(function) diff --git a/returns/_generated/pointfree/map.pyi b/returns/_generated/pointfree/map.pyi deleted file mode 100644 index edfc9b34c..000000000 --- a/returns/_generated/pointfree/map.pyi +++ /dev/null @@ -1,108 +0,0 @@ -from typing import Callable, TypeVar, overload - -from typing_extensions import Protocol - -from returns.context import ( - RequiresContext, - RequiresContextFutureResult, - RequiresContextIOResult, - RequiresContextResult, -) -from returns.future import Future, FutureResult -from returns.io import IO, IOResult -from returns.maybe import Maybe -from returns.result import Result - -_ValueType = TypeVar('_ValueType', contravariant=True) -_ErrorType = TypeVar('_ErrorType') -_NewValueType = TypeVar('_NewValueType', covariant=True) -_EnvType = TypeVar('_EnvType', contravariant=True) - - -class _Mappable(Protocol[_ValueType, _NewValueType]): - """ - Helper class to represent type overloads for ret_type based on a value type. - - Contains all containers we have. - - It does not exist in runtime. - It is also completely removed from typing with the help of the mypy plugin. - """ - - @overload - def __call__( - self, - container: Maybe[_ValueType], - ) -> Maybe[_NewValueType]: - ... - - @overload - def __call__( - self, - container: IO[_ValueType], - ) -> IO[_NewValueType]: - ... - - @overload - def __call__( - self, - container: RequiresContext[_EnvType, _ValueType], - ) -> RequiresContext[_EnvType, _NewValueType]: - ... - - @overload - def __call__( - self, - container: RequiresContextResult[_EnvType, _ValueType, _ErrorType], - ) -> RequiresContextResult[_EnvType, _NewValueType, _ErrorType]: - ... - - @overload - def __call__( - self, - container: RequiresContextIOResult[_EnvType, _ValueType, _ErrorType], - ) -> RequiresContextIOResult[_EnvType, _NewValueType, _ErrorType]: - ... - - @overload - def __call__( - self, - container: RequiresContextFutureResult[ - _EnvType, _ValueType, _ErrorType, - ], - ) -> RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType]: - ... - - @overload - def __call__( - self, - container: Result[_ValueType, _ErrorType], - ) -> Result[_NewValueType, _ErrorType]: - ... - - @overload - def __call__( - self, - container: IOResult[_ValueType, _ErrorType], - ) -> IOResult[_NewValueType, _ErrorType]: - ... - - @overload - def __call__( - self, - container: Future[_ValueType], - ) -> Future[_NewValueType]: - ... - - @overload - def __call__( - self, - container: FutureResult[_ValueType, _ErrorType], - ) -> FutureResult[_NewValueType, _ErrorType]: - ... - - -def _map( - function: Callable[[_ValueType], _NewValueType], -) -> _Mappable[_ValueType, _NewValueType]: - ... diff --git a/returns/_generated/pointfree/rescue.py b/returns/_generated/pointfree/rescue.py deleted file mode 100644 index 1da273ce0..000000000 --- a/returns/_generated/pointfree/rescue.py +++ /dev/null @@ -1,27 +0,0 @@ -def _rescue(function): - """ - Turns function's input parameter from a regular value to a container. - - In other words, it modifies the function - signature from: ``a -> Container[b]`` to: ``Container[a] -> Container[b]`` - - Similar to :func:`returns.pointfree.bind`, but works for failed containers. - - This is how it should be used: - - .. code:: python - - >>> from returns.pointfree import rescue - >>> from returns.result import Success, Failure, Result - - >>> def example(argument: int) -> Result[str, int]: - ... return Success(argument + 1) - - >>> assert rescue(example)(Success('a')) == Success('a') - >>> assert rescue(example)(Failure(1)) == Success(2) - - Note, that this function works for all containers with ``.rescue`` method. - See :class:`returns.primitives.interfaces.Rescueable` for more info. - - """ - return lambda container: container.rescue(function) diff --git a/returns/_generated/pointfree/rescue.pyi b/returns/_generated/pointfree/rescue.pyi deleted file mode 100644 index c88ee597e..000000000 --- a/returns/_generated/pointfree/rescue.pyi +++ /dev/null @@ -1,87 +0,0 @@ -from typing import Callable, TypeVar, overload - -from returns.context import ( - RequiresContextFutureResult, - RequiresContextIOResult, - RequiresContextResult, -) -from returns.future import FutureResult -from returns.io import IOResult -from returns.result import Result - -# Result: -_ValueType = TypeVar('_ValueType', contravariant=True) -_ErrorType = TypeVar('_ErrorType') -_NewErrorType = TypeVar('_NewErrorType') - -# Context: -_EnvType = TypeVar('_EnvType', contravariant=True) - - -@overload -def _rescue( - function: Callable[[_ErrorType], Result[_ValueType, _NewErrorType]], -) -> Callable[ - [Result[_ValueType, _ErrorType]], - Result[_ValueType, _NewErrorType], -]: - ... - - -@overload -def _rescue( - function: Callable[[_ErrorType], IOResult[_ValueType, _NewErrorType]], -) -> Callable[ - [IOResult[_ValueType, _ErrorType]], - IOResult[_ValueType, _NewErrorType], -]: - ... - - -@overload -def _rescue( - function: Callable[ - [_ErrorType], - RequiresContextResult[_EnvType, _ValueType, _NewErrorType], - ], -) -> Callable[ - [RequiresContextResult[_EnvType, _ValueType, _ErrorType]], - RequiresContextResult[_EnvType, _ValueType, _NewErrorType], -]: - ... - - -@overload -def _rescue( - function: Callable[ - [_ErrorType], - RequiresContextIOResult[_EnvType, _ValueType, _NewErrorType], - ], -) -> Callable[ - [RequiresContextIOResult[_EnvType, _ValueType, _ErrorType]], - RequiresContextIOResult[_EnvType, _ValueType, _NewErrorType], -]: - ... - - -@overload -def _rescue( - function: Callable[ - [_ErrorType], - RequiresContextFutureResult[_EnvType, _ValueType, _NewErrorType], - ], -) -> Callable[ - [RequiresContextFutureResult[_EnvType, _ValueType, _ErrorType]], - RequiresContextFutureResult[_EnvType, _ValueType, _NewErrorType], -]: - ... - - -@overload -def _rescue( - function: Callable[[_ErrorType], FutureResult[_ValueType, _NewErrorType]], -) -> Callable[ - [FutureResult[_ValueType, _ErrorType]], - FutureResult[_ValueType, _NewErrorType], -]: - ... diff --git a/returns/_generated/pointfree/unify.py b/returns/_generated/pointfree/unify.py deleted file mode 100644 index 876c1f38d..000000000 --- a/returns/_generated/pointfree/unify.py +++ /dev/null @@ -1,32 +0,0 @@ -def _unify(function): - """ - Turns function's input parameter from a regular value to a container. - - In other words, it modifies the function - signature from: ``a -> Container[b]`` to: ``Container[a] -> Container[b]`` - - Similar to :func:`returns.pointfree.bind`, - but unifies the result error type to become - ``Union[_ErrorType, _NewErrorType]``. - - Similar to :func:`returns.pointfree.rescue`, - but works for successful containers. - - This is how it should be used: - - .. code:: python - - >>> from returns.pointfree import unify - >>> from returns.result import Success, Result, Failure - - >>> def example(argument: int) -> Result[int, str]: - ... return Success(argument + 1) - - >>> assert unify(example)(Success(1)) == Success(2) - >>> assert unify(example)(Failure('a')) == Failure('a') - - Note, that this function works for all containers with ``.unify`` method. - See :class:`returns.primitives.interfaces.Bindable` for more info. - - """ - return lambda container: container.unify(function) diff --git a/returns/_generated/pointfree/unify.pyi b/returns/_generated/pointfree/unify.pyi deleted file mode 100644 index d7c4cd86f..000000000 --- a/returns/_generated/pointfree/unify.pyi +++ /dev/null @@ -1,43 +0,0 @@ -from typing import Callable, TypeVar, Union, overload - -from returns.future import FutureResult -from returns.io import IOResult -from returns.result import Result - -_ValueType = TypeVar('_ValueType') -_ErrorType = TypeVar('_ErrorType') -_NewValueType = TypeVar('_NewValueType') -_NewErrorType = TypeVar('_NewErrorType') - - -@overload -def _unify( - function: Callable[[_ValueType], Result[_NewValueType, _NewErrorType]], -) -> Callable[ - [Result[_ValueType, _ErrorType]], - Result[_NewValueType, Union[_ErrorType, _NewErrorType]], -]: - ... - - -@overload -def _unify( - function: Callable[[_ValueType], IOResult[_NewValueType, _NewErrorType]], -) -> Callable[ - [IOResult[_ValueType, _ErrorType]], - IOResult[_NewValueType, Union[_ErrorType, _NewErrorType]], -]: - ... - - -@overload -def _unify( - function: Callable[ - [_ValueType], - FutureResult[_NewValueType, _NewErrorType], - ], -) -> Callable[ - [FutureResult[_ValueType, _ErrorType]], - FutureResult[_NewValueType, Union[_ErrorType, _NewErrorType]], -]: - ... diff --git a/returns/_generated/pointfree/value_or.py b/returns/_generated/pointfree/value_or.py deleted file mode 100644 index da726b59b..000000000 --- a/returns/_generated/pointfree/value_or.py +++ /dev/null @@ -1,29 +0,0 @@ -def _value_or(default_value): - """ - Get value from successful container or default value from failed one. - - .. code:: python - - >>> import anyio - >>> from returns.pointfree import value_or - >>> from returns.io import IO, IOFailure, IOSuccess - >>> from returns.maybe import Some, Nothing - >>> from returns.context import ReaderFutureResult - - >>> assert value_or(2)(IOSuccess(1)) == IO(1) - >>> assert value_or(2)(IOFailure(1)) == IO(2) - - >>> assert value_or(2)(Some(1)) == 1 - >>> assert value_or(2)(Nothing) == 2 - - >>> assert anyio.run( - ... value_or(2)(ReaderFutureResult.from_value(1)), - ... ReaderFutureResult.empty, - ... ) == IO(1) - >>> assert anyio.run( - ... value_or(2)(ReaderFutureResult.from_failure(1)), - ... ReaderFutureResult.empty, - ... ) == IO(2) - - """ - return lambda container: container.value_or(default_value) diff --git a/returns/_generated/pointfree/value_or.pyi b/returns/_generated/pointfree/value_or.pyi deleted file mode 100644 index 6f6398625..000000000 --- a/returns/_generated/pointfree/value_or.pyi +++ /dev/null @@ -1,89 +0,0 @@ -from typing import Awaitable, Callable, TypeVar, Union, overload - -from typing_extensions import Protocol - -from returns.context import ( - RequiresContextFutureResult, - RequiresContextIOResult, - RequiresContextResult, -) -from returns.future import FutureResult -from returns.io import IO, IOResult -from returns.maybe import Maybe -from returns.result import Result - -_ValueType = TypeVar('_ValueType', contravariant=True) -_NewValueType = TypeVar('_NewValueType') -_ErrorType = TypeVar('_ErrorType') -_EnvType = TypeVar('_EnvType', contravariant=True) - - -_FirstType = TypeVar('_FirstType', covariant=True) - - -class _ValueOr(Protocol[_FirstType]): - """ - Helper class to represent type overloads for ret_type based on a value type. - - Contains all containers we have. - - It does not exist in runtime. - It is also completely removed from typing with the help of the mypy plugin. - """ - - @overload - def __call__( - self, - container: Maybe[_ValueType], - ) -> Union[_ValueType, _FirstType]: - ... - - @overload - def __call__( - self, - container: RequiresContextResult[_EnvType, _ValueType, _ErrorType], - ) -> Callable[[_EnvType], Union[_ValueType, _FirstType]]: - ... - - @overload - def __call__( - self, - container: RequiresContextIOResult[_EnvType, _ValueType, _ErrorType], - ) -> Callable[[_EnvType], IO[Union[_ValueType, _FirstType]]]: - ... - - @overload # noqa: WPS234 - def __call__( # noqa: WPS234 - self, - container: RequiresContextFutureResult[ - _EnvType, _ValueType, _ErrorType, - ], - ) -> Callable[[_EnvType], Awaitable[IO[Union[_ValueType, _FirstType]]]]: - ... - - @overload - def __call__( - self, - container: Result[_ValueType, _ErrorType], - ) -> Union[_ValueType, _FirstType]: - ... - - @overload - def __call__( - self, - container: IOResult[_ValueType, _ErrorType], - ) -> IO[Union[_ValueType, _FirstType]]: - ... - - @overload - def __call__( - self, - container: FutureResult[_ValueType, _ErrorType], - ) -> Awaitable[IO[Union[_ValueType, _FirstType]]]: - ... - - -def _value_or( - default_value: _NewValueType, -) -> _ValueOr[_NewValueType]: - ... diff --git a/returns/context/requires_context.py b/returns/context/requires_context.py index 83375f4e6..9f7c31fe9 100644 --- a/returns/context/requires_context.py +++ b/returns/context/requires_context.py @@ -14,8 +14,13 @@ from returns._generated.iterable import iterable from returns.functions import identity +from returns.future import FutureResult +from returns.interfaces import applicative, bindable, mappable +from returns.io import IOResult from returns.primitives.container import BaseContainer +from returns.primitives.hkt import Kind2, dekind from returns.primitives.types import Immutable +from returns.result import Result if TYPE_CHECKING: # We need this condition to make sure Python can solve cycle imports. @@ -24,8 +29,9 @@ RequiresContextIOResult, ) from returns.context.requires_context_result import RequiresContextResult - from returns.io import IOResult - from returns.result import Result + from returns.context.requires_context_future_result import ( + RequiresContextFutureResult, + ) # Context: _EnvType = TypeVar('_EnvType', contravariant=True) @@ -47,7 +53,10 @@ @final class RequiresContext( BaseContainer, - Generic[_EnvType, _ReturnType], + Kind2['RequiresContext', _ReturnType, _EnvType], + mappable.Mappable2[_ReturnType, _EnvType], + bindable.Bindable2[_ReturnType, _EnvType], + applicative.Applicative2[_ReturnType, _EnvType], ): """ The ``RequiresContext`` container. @@ -86,7 +95,8 @@ class RequiresContext( empty: ClassVar[NoDeps] = object() def __init__( - self, inner_value: Callable[[_EnvType], _ReturnType], + self, + inner_value: Callable[[_EnvType], _ReturnType], ) -> None: """ Public constructor for this type. Also required for typing. @@ -110,7 +120,7 @@ def __call__(self, deps: _EnvType) -> _ReturnType: >>> from returns.context import RequiresContext - >>> def first(lg: bool) -> RequiresContext[float, int]: + >>> def first(lg: bool) -> RequiresContext[int, float]: ... # `deps` has `float` type here: ... return RequiresContext( ... lambda deps: deps if lg else -deps, @@ -128,7 +138,7 @@ def __call__(self, deps: _EnvType) -> _ReturnType: def map( # noqa: WPS125 self, function: Callable[[_ReturnType], _NewReturnType], - ) -> 'RequiresContext[_EnvType, _NewReturnType]': + ) -> 'RequiresContext[_NewReturnType, _EnvType]': """ Allows to compose functions inside the wrapped container. @@ -137,7 +147,7 @@ def map( # noqa: WPS125 .. code:: python >>> from returns.context import RequiresContext - >>> def first(lg: bool) -> RequiresContext[float, int]: + >>> def first(lg: bool) -> RequiresContext[int, float]: ... # `deps` has `float` type here: ... return RequiresContext( ... lambda deps: deps if lg else -deps, @@ -151,8 +161,12 @@ def map( # noqa: WPS125 def apply( self, - container: 'Reader[_EnvType, Callable[[_ReturnType], _NewReturnType]]', - ) -> 'RequiresContext[_EnvType, _NewReturnType]': + container: Kind2[ + 'RequiresContext', + Callable[[_ReturnType], _NewReturnType], + _EnvType, + ], + ) -> 'RequiresContext[_NewReturnType, _EnvType]': """ Calls a wrapped function in a container on this container. @@ -164,15 +178,17 @@ def apply( ... )(...) == 'ab' """ - return RequiresContext(lambda deps: self.map(container(deps))(deps)) + return RequiresContext( + lambda deps: self.map(dekind(container)(deps))(deps), + ) def bind( self, function: Callable[ [_ReturnType], - 'RequiresContext[_EnvType, _NewReturnType]', + Kind2['RequiresContext', _NewReturnType, _EnvType], ], - ) -> 'RequiresContext[_EnvType, _NewReturnType]': + ) -> 'RequiresContext[_NewReturnType, _EnvType]': """ Composes a container with a function returning another container. @@ -183,13 +199,13 @@ def bind( >>> from returns.context import RequiresContext - >>> def first(lg: bool) -> RequiresContext[float, int]: + >>> def first(lg: bool) -> RequiresContext[int, float]: ... # `deps` has `float` type here: ... return RequiresContext( ... lambda deps: deps if lg else -deps, ... ) - >>> def second(number: int) -> RequiresContext[float, str]: + >>> def second(number: int) -> RequiresContext[str, float]: ... # `deps` has `float` type here: ... return RequiresContext( ... lambda deps: '>=' if number >= deps else '<', @@ -199,12 +215,12 @@ def bind( >>> assert first(False).bind(second)(2) == '<' """ - return RequiresContext(lambda deps: function(self(deps))(deps)) + return RequiresContext(lambda deps: dekind(function(self(deps)))(deps)) @classmethod def from_value( cls, inner_value: _FirstType, - ) -> 'RequiresContext[NoDeps, _FirstType]': + ) -> 'RequiresContext[_FirstType, NoDeps]': """ Used to return some specific value from the container. @@ -220,9 +236,6 @@ def from_value( >>> assert unit(RequiresContext.empty) == 5 Might be used with or without direct type hint. - - Part of the :class:`returns.primitives.interfaces.Applicative` - protocol. """ return RequiresContext(lambda _: inner_value) @@ -230,7 +243,7 @@ def from_value( def from_iterable( cls, inner_value: Iterable['RequiresContext[_EnvType, _ValueType]'], - ) -> 'RequiresContext[_EnvType, Sequence[_ValueType]]': + ) -> 'RequiresContext[Sequence[_ValueType], _EnvType]': """ Transforms an iterable of ``RequiresContext`` containers. @@ -251,13 +264,13 @@ def from_iterable( @classmethod def from_requires_context_result( cls, - inner_value: 'RequiresContextResult[_EnvType, _ValueType, _ErrorType]', - ) -> 'RequiresContext[_EnvType, Result[_ValueType, _ErrorType]]': + inner_value: 'RequiresContextResult[_ValueType, _ErrorType, _EnvType]', + ) -> 'RequiresContext[Result[_ValueType, _ErrorType], _EnvType]': """ Typecasts ``RequiresContextResult`` to ``RequiresContext`` instance. - Breaks ``RequiresContextResult[e, a, b]`` - into ``RequiresContext[e, Result[a, b]]``. + Breaks ``RequiresContextResult[a, b, e]`` + into ``RequiresContext[Result[a, b], e]``. .. code:: python @@ -277,13 +290,13 @@ def from_requires_context_result( def from_requires_context_ioresult( cls, inner_value: - 'RequiresContextIOResult[_EnvType, _ValueType, _ErrorType]', - ) -> 'RequiresContext[_EnvType, IOResult[_ValueType, _ErrorType]]': + 'RequiresContextIOResult[_ValueType, _ErrorType, _EnvType]', + ) -> 'RequiresContext[IOResult[_ValueType, _ErrorType], _EnvType]': """ Typecasts ``RequiresContextIOResult`` to ``RequiresContext`` instance. - Breaks ``RequiresContextIOResult[e, a, b]`` - into ``RequiresContext[e, IOResult[a, b]]``. + Breaks ``RequiresContextIOResult[a, b, e]`` + into ``RequiresContext[IOResult[a, b], e]``. .. code:: python @@ -299,6 +312,37 @@ def from_requires_context_ioresult( """ return RequiresContext(inner_value) + @classmethod + def from_requires_context_future_result( + cls, + inner_value: + 'RequiresContextFutureResult[_ValueType, _ErrorType, _EnvType]', + ) -> 'RequiresContext[FutureResult[_ValueType, _ErrorType], _EnvType]': + """ + Typecasts ``RequiresContextIOResult`` to ``RequiresContext`` instance. + + Breaks ``RequiresContextIOResult[a, b, e]`` + into ``RequiresContext[IOResult[a, b], e]``. + + .. code:: python + + >>> import anyio + >>> from returns.context import RequiresContext + >>> from returns.context import RequiresContextFutureResult + >>> from returns.io import IOSuccess + + >>> container = RequiresContext.from_requires_context_future_result( + ... RequiresContextFutureResult.from_value(1), + ... ) + >>> assert anyio.run( + ... container, RequiresContext.empty, + ... ) == IOSuccess(1) + + Can be reverted with ``RequiresContextFutureResult.from_typecast``. + + """ + return RequiresContext(inner_value) + @final class Context(Immutable, Generic[_EnvType], metaclass=ABCMeta): @@ -348,7 +392,7 @@ def ask(cls) -> RequiresContext[_EnvType, _EnvType]: >>> class Deps(TypedDict): ... message: str - >>> def first(lg: bool) -> RequiresContext[Deps, int]: + >>> def first(lg: bool) -> RequiresContext[int, Deps]: ... # `deps` has `Deps` type here: ... return RequiresContext( ... lambda deps: deps['message'] if lg else 'error', @@ -371,7 +415,7 @@ def ask(cls) -> RequiresContext[_EnvType, _EnvType]: ... message: str ... limit: int # note this new field! - >>> def new_first(lg: bool) -> RequiresContext[Deps, int]: + >>> def new_first(lg: bool) -> RequiresContext[int, Deps]: ... # `deps` has `Deps` type here: ... return RequiresContext( ... lambda deps: deps['message'] if lg else 'err', diff --git a/returns/context/requires_context_future_result.py b/returns/context/requires_context_future_result.py index 20695e6e1..46198ff34 100644 --- a/returns/context/requires_context_future_result.py +++ b/returns/context/requires_context_future_result.py @@ -9,26 +9,28 @@ Iterable, Sequence, TypeVar, - Union, ) from typing_extensions import final -from returns._generated.futures import _future_result, _reader_future_result +from returns._generated.futures import _reader_future_result from returns._generated.iterable import iterable from returns.context import NoDeps from returns.future import Future, FutureResult +from returns.interfaces import applicative, bindable, mappable, rescuable +from returns.interfaces.specific import result from returns.io import IO, IOResult from returns.primitives.container import BaseContainer +from returns.primitives.hkt import Kind3, dekind from returns.primitives.types import Immutable from returns.result import Result if TYPE_CHECKING: from returns.context.requires_context import RequiresContext - from returns.context.requires_context_result import RequiresContextResult from returns.context.requires_context_ioresult import ( RequiresContextIOResult, ) + from returns.context.requires_context_result import RequiresContextResult # Context: _EnvType = TypeVar('_EnvType', contravariant=True) @@ -46,7 +48,12 @@ @final class RequiresContextFutureResult( BaseContainer, - Generic[_EnvType, _ValueType, _ErrorType], + Kind3['RequiresContextFutureResult', _ValueType, _ErrorType, _EnvType], + mappable.Mappable3[_ValueType, _ErrorType, _EnvType], + bindable.Bindable3[_ValueType, _ErrorType, _EnvType], + applicative.Applicative3[_ValueType, _ErrorType, _EnvType], + rescuable.Rescuable3[_ValueType, _ErrorType, _EnvType], + result.ResultBased3[_ValueType, _ErrorType, _EnvType], ): """ The ``RequiresContextFutureResult`` combinator. @@ -142,7 +149,7 @@ def __call__(self, deps: _EnvType) -> FutureResult[_ValueType, _ErrorType]: >>> from returns.future import FutureResult >>> from returns.io import IOSuccess - >>> def first(lg: bool) -> RequiresContextFutureResult[int, int, str]: + >>> def first(lg: bool) -> RequiresContextFutureResult[int, str, int]: ... # `deps` has `int` type here: ... return RequiresContextFutureResult( ... lambda deps: FutureResult.from_value( @@ -164,7 +171,7 @@ def __call__(self, deps: _EnvType) -> FutureResult[_ValueType, _ErrorType]: def map( # noqa: WPS125 self, function: Callable[[_ValueType], _NewValueType], - ) -> 'RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType]': + ) -> 'RequiresContextFutureResult[_NewValueType, _ErrorType, _EnvType]': """ Composes successful container with a pure function. @@ -189,9 +196,13 @@ def map( # noqa: WPS125 def apply( self, - container: 'RequiresContextFutureResult[' - '_EnvType, Callable[[_ValueType], _NewValueType], _ErrorType]', - ) -> 'RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType]': + container: Kind3[ + 'RequiresContextFutureResult', + Callable[[_ValueType], _NewValueType], + _ErrorType, + _EnvType, + ], + ) -> 'RequiresContextFutureResult[_NewValueType, _ErrorType, _EnvType]': """ Calls a wrapped function in a container on this container. @@ -220,16 +231,21 @@ def apply( """ return RequiresContextFutureResult( - lambda deps: self(deps).apply(container(deps)), + lambda deps: self(deps).apply(dekind(container)(deps)), ) def bind( self, function: Callable[ [_ValueType], - 'RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType]', + Kind3[ + 'RequiresContextFutureResult', + _NewValueType, + _ErrorType, + _EnvType, + ], ], - ) -> 'RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType]': + ) -> 'RequiresContextFutureResult[_NewValueType, _ErrorType, _EnvType]': """ Composes this container with a function returning the same type. @@ -242,7 +258,7 @@ def bind( >>> def function( ... number: int, - ... ) -> RequiresContextFutureResult[int, str, int]: + ... ) -> RequiresContextFutureResult[str, int, int]: ... # `deps` has `int` type here: ... return RequiresContextFutureResult( ... lambda deps: FutureResult.from_value(str(number + deps)), @@ -260,7 +276,9 @@ def bind( """ return RequiresContextFutureResult( lambda deps: self(deps).bind( - lambda inner: function(inner)(deps), # type: ignore[misc] + lambda inner: dekind( # type: ignore[misc] + function(inner), + )(deps), ), ) @@ -270,10 +288,10 @@ def bind_async( [_ValueType], Awaitable[ 'RequiresContextFutureResult' - '[_EnvType, _NewValueType, _ErrorType]' + '[_NewValueType, _ErrorType, _EnvType]' ], ], - ) -> 'RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType]': + ) -> 'RequiresContextFutureResult[_NewValueType, _ErrorType, _EnvType]': """ Composes this container with a async function returning the same type. @@ -285,7 +303,7 @@ def bind_async( >>> async def function( ... number: int, - ... ) -> RequiresContextFutureResult[int, str, int]: + ... ) -> RequiresContextFutureResult[str, int, int]: ... return RequiresContextFutureResult.from_value(number + 1) >>> assert anyio.run( @@ -311,7 +329,7 @@ def bind_async( def bind_awaitable( self, function: Callable[[_ValueType], 'Awaitable[_NewValueType]'], - ) -> 'RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType]': + ) -> 'RequiresContextFutureResult[_NewValueType, _ErrorType, _EnvType]': """ Allows to compose a container and a regular ``async`` function. @@ -350,7 +368,7 @@ def bind_awaitable( def bind_result( self, function: Callable[[_ValueType], 'Result[_NewValueType, _ErrorType]'], - ) -> 'RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType]': + ) -> 'RequiresContextFutureResult[_NewValueType, _ErrorType, _EnvType]': """ Binds ``Result`` returning function to the current container. @@ -387,9 +405,9 @@ def bind_context( self, function: Callable[ [_ValueType], - 'RequiresContext[_EnvType, _NewValueType]', + 'RequiresContext[_NewValueType, _EnvType]', ], - ) -> 'RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType]': + ) -> 'RequiresContextFutureResult[_NewValueType, _ErrorType, _EnvType]': """ Binds ``RequiresContext`` returning function to current container. @@ -399,7 +417,7 @@ def bind_context( >>> from returns.context import RequiresContext >>> from returns.io import IOSuccess, IOFailure - >>> def function(arg: int) -> RequiresContext[str, int]: + >>> def function(arg: int) -> RequiresContext[int, str]: ... return RequiresContext(lambda deps: len(deps) + arg) >>> assert anyio.run( @@ -427,9 +445,9 @@ def bind_context_result( self, function: Callable[ [_ValueType], - 'RequiresContextResult[_EnvType, _NewValueType, _ErrorType]', + 'RequiresContextResult[_NewValueType, _ErrorType, _EnvType]', ], - ) -> 'RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType]': + ) -> 'RequiresContextFutureResult[_NewValueType, _ErrorType, _EnvType]': """ Binds ``RequiresContextResult`` returning function to the current one. @@ -440,7 +458,7 @@ def bind_context_result( >>> from returns.io import IOSuccess, IOFailure >>> from returns.result import Success - >>> def function(arg: int) -> RequiresContextResult[str, int, int]: + >>> def function(arg: int) -> RequiresContextResult[int, int, str]: ... return RequiresContextResult( ... lambda deps: Success(len(deps) + arg), ... ) @@ -470,9 +488,9 @@ def bind_context_ioresult( self, function: Callable[ [_ValueType], - 'RequiresContextIOResult[_EnvType, _NewValueType, _ErrorType]', + 'RequiresContextIOResult[_NewValueType, _ErrorType, _EnvType]', ], - ) -> 'RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType]': + ) -> 'RequiresContextFutureResult[_NewValueType, _ErrorType, _EnvType]': """ Binds ``RequiresContextIOResult`` returning function to the current one. @@ -482,7 +500,7 @@ def bind_context_ioresult( >>> from returns.context import RequiresContextIOResult >>> from returns.io import IOSuccess, IOFailure - >>> def function(arg: int) -> RequiresContextIOResult[str, int, int]: + >>> def function(arg: int) -> RequiresContextIOResult[int, int, str]: ... return RequiresContextIOResult( ... lambda deps: IOSuccess(len(deps) + arg), ... ) @@ -511,7 +529,7 @@ def bind_context_ioresult( def bind_io( self, function: Callable[[_ValueType], IO[_NewValueType]], - ) -> 'RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType]': + ) -> 'RequiresContextFutureResult[_NewValueType, _ErrorType, _EnvType]': """ Binds ``IO`` returning function to the current container. @@ -542,7 +560,7 @@ def bind_io( def bind_ioresult( self, function: Callable[[_ValueType], IOResult[_NewValueType, _ErrorType]], - ) -> 'RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType]': + ) -> 'RequiresContextFutureResult[_NewValueType, _ErrorType, _EnvType]': """ Binds ``IOResult`` returning function to the current container. @@ -577,7 +595,7 @@ def bind_ioresult( def bind_future( self, function: Callable[[_ValueType], Future[_NewValueType]], - ) -> 'RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType]': + ) -> 'RequiresContextFutureResult[_NewValueType, _ErrorType, _EnvType]': """ Binds ``Future`` returning function to the current container. @@ -615,7 +633,7 @@ def bind_future_result( [_ValueType], FutureResult[_NewValueType, _ErrorType], ], - ) -> 'RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType]': + ) -> 'RequiresContextFutureResult[_NewValueType, _ErrorType, _EnvType]': """ Binds ``FutureResult`` returning function to the current container. @@ -650,7 +668,7 @@ def bind_future_result( def bind_async_future( self, function: Callable[[_ValueType], Awaitable[Future[_NewValueType]]], - ) -> 'RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType]': + ) -> 'RequiresContextFutureResult[_NewValueType, _ErrorType, _EnvType]': """ Binds ``Future`` returning async function to the current container. @@ -688,7 +706,7 @@ def bind_async_future_result( [_ValueType], Awaitable[FutureResult[_NewValueType, _ErrorType]], ], - ) -> 'RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType]': + ) -> 'RequiresContextFutureResult[_NewValueType, _ErrorType, _EnvType]': """ Bind ``FutureResult`` returning async function to the current container. @@ -724,7 +742,7 @@ def bind_async_future_result( def fix( self, function: Callable[[_ErrorType], _NewValueType], - ) -> 'RequiresContextFutureResult[_EnvType, _NewValueType, _ErrorType]': + ) -> 'RequiresContextFutureResult[_NewValueType, _ErrorType, _EnvType]': """ Composes failed container with a pure function. @@ -755,7 +773,7 @@ def fix( def alt( self, function: Callable[[_ErrorType], _NewErrorType], - ) -> 'RequiresContextFutureResult[_EnvType, _ValueType, _NewErrorType]': + ) -> 'RequiresContextFutureResult[_ValueType, _NewErrorType, _EnvType]': """ Composes failed container with a pure function. @@ -788,9 +806,14 @@ def rescue( self, function: Callable[ [_ErrorType], - 'RequiresContextFutureResult[_EnvType, _ValueType, _NewErrorType]', + Kind3[ + 'RequiresContextFutureResult', + _ValueType, + _NewErrorType, + _EnvType, + ], ], - ) -> 'RequiresContextFutureResult[_EnvType, _ValueType, _NewErrorType]': + ) -> 'RequiresContextFutureResult[_ValueType, _NewErrorType, _EnvType]': """ Composes this container with a function returning the same type. @@ -825,96 +848,14 @@ def rescue( """ return RequiresContextFutureResult( lambda deps: self(deps).rescue( - lambda inner: function(inner)(deps), # type: ignore[misc] + lambda inner: function(inner)(deps), # type: ignore ), ) - def value_or( # noqa: WPS234 - self, default_value: _FirstType, - ) -> Callable[ - [_EnvType], - Awaitable[IO[Union[_ValueType, _FirstType]]], - ]: - """ - Returns a callable that either returns a success or default value. - - .. code:: python - - >>> import anyio - >>> from returns.context import RequiresContextFutureResult - >>> from returns.io import IO - - >>> assert anyio.run( - ... RequiresContextFutureResult.from_value(1).value_or(2), - ... RequiresContextFutureResult.empty, - ... ) == IO(1) - - >>> assert anyio.run( - ... RequiresContextFutureResult.from_failure(1).value_or(2), - ... RequiresContextFutureResult.empty, - ... ) == IO(2) - - """ - return lambda deps: _future_result.async_value_or( - self(deps), default_value, - ) - - def unwrap(self) -> Callable[[_EnvType], Awaitable[IO[_ValueType]]]: - """ - Returns a callable that unwraps success value or raises exception. - - .. code:: pycon - - >>> import anyio - >>> from returns.context import RequiresContextFutureResult - >>> from returns.io import IO - - >>> assert anyio.run( - ... RequiresContextFutureResult.from_value(1).unwrap(), - ... RequiresContextFutureResult.empty, - ... ) == IO(1) - - >>> anyio.run( - ... RequiresContextFutureResult.from_failure(1).unwrap(), - ... RequiresContextFutureResult.empty, - ... ) - Traceback (most recent call last): - ... - returns.primitives.exceptions.UnwrapFailedError - - """ - return lambda deps: _future_result.async_unwrap(self(deps)) - - def failure(self) -> Callable[[_EnvType], Awaitable[IO[_ErrorType]]]: - """ - Returns a callable that unwraps failure value or raises exception. - - .. code:: pycon - - >>> import anyio - >>> from returns.context import RequiresContextFutureResult - >>> from returns.io import IO - - >>> assert anyio.run( - ... RequiresContextFutureResult.from_failure(1).failure(), - ... RequiresContextFutureResult.empty, - ... ) == IO(1) - - >>> anyio.run( - ... RequiresContextFutureResult.from_value(1).failure(), - ... RequiresContextFutureResult.empty, - ... ) - Traceback (most recent call last): - ... - returns.primitives.exceptions.UnwrapFailedError - - """ - return lambda deps: _future_result.async_failure(self(deps)) - @classmethod def from_result( cls, inner_value: Result[_ValueType, _ErrorType], - ) -> 'RequiresContextFutureResult[NoDeps, _ValueType, _ErrorType]': + ) -> 'RequiresContextFutureResult[_ValueType, _ErrorType, NoDeps]': """ Creates new container with ``Result`` as a unit value. @@ -944,7 +885,7 @@ def from_result( def from_io( cls, inner_value: IO[_NewValueType], - ) -> 'RequiresContextFutureResult[NoDeps, _NewValueType, Any]': + ) -> 'RequiresContextFutureResult[_NewValueType, Any, NoDeps]': """ Creates new container from successful ``IO`` value. @@ -968,7 +909,7 @@ def from_io( def from_failed_io( cls, inner_value: IO[_NewErrorType], - ) -> 'RequiresContextFutureResult[NoDeps, Any, _NewErrorType]': + ) -> 'RequiresContextFutureResult[Any, _NewErrorType, NoDeps]': """ Creates a new container from failed ``IO`` value. @@ -991,7 +932,7 @@ def from_failed_io( @classmethod def from_ioresult( cls, inner_value: IOResult[_ValueType, _ErrorType], - ) -> 'RequiresContextFutureResult[NoDeps, _ValueType, _ErrorType]': + ) -> 'RequiresContextFutureResult[_ValueType, _ErrorType, NoDeps]': """ Creates new container with ``IOResult`` as a unit value. @@ -1020,7 +961,7 @@ def from_ioresult( def from_future( cls, inner_value: Future[_ValueType], - ) -> 'RequiresContextFutureResult[NoDeps, _ValueType, Any]': + ) -> 'RequiresContextFutureResult[_ValueType, Any, NoDeps]': """ Creates new container with successful ``Future`` as a unit value. @@ -1045,7 +986,7 @@ def from_future( def from_failed_future( cls, inner_value: Future[_ErrorType], - ) -> 'RequiresContextFutureResult[NoDeps, Any, _ErrorType]': + ) -> 'RequiresContextFutureResult[Any, _ErrorType, NoDeps]': """ Creates new container with failed ``Future`` as a unit value. @@ -1072,7 +1013,7 @@ def from_failed_future( def from_future_result( cls, inner_value: FutureResult[_ValueType, _ErrorType], - ) -> 'RequiresContextFutureResult[NoDeps, _ValueType, _ErrorType]': + ) -> 'RequiresContextFutureResult[_ValueType, _ErrorType, NoDeps]': """ Creates new container with ``FutureResult`` as a unit value. @@ -1104,8 +1045,8 @@ def from_future_result( def from_typecast( cls, inner_value: 'RequiresContext[' - '_EnvType, FutureResult[_NewValueType, _NewErrorType]]', - ) -> 'RequiresContextFutureResult[_EnvType, _NewValueType, _NewErrorType]': + 'FutureResult[_NewValueType, _NewErrorType], _EnvType]', + ) -> 'RequiresContextFutureResult[_NewValueType, _NewErrorType, _EnvType]': """ You might end up with ``RequiresContext[FutureResult]`` as a value. @@ -1140,8 +1081,8 @@ def from_typecast( @classmethod def from_context( - cls, inner_value: 'RequiresContext[_EnvType, _FirstType]', - ) -> 'RequiresContextFutureResult[_EnvType, _FirstType, Any]': + cls, inner_value: 'RequiresContext[_FirstType, _EnvType]', + ) -> 'RequiresContextFutureResult[_FirstType, Any, _EnvType]': """ Creates new container from ``RequiresContext`` as a success unit. @@ -1165,8 +1106,8 @@ def from_context( @classmethod def from_failed_context( - cls, inner_value: 'RequiresContext[_EnvType, _FirstType]', - ) -> 'RequiresContextFutureResult[_EnvType, Any, _FirstType]': + cls, inner_value: 'RequiresContext[_FirstType, _EnvType]', + ) -> 'RequiresContextFutureResult[Any, _FirstType, _EnvType]': """ Creates new container from ``RequiresContext`` as a failure unit. @@ -1191,8 +1132,8 @@ def from_failed_context( @classmethod def from_result_context( cls, - inner_value: 'RequiresContextResult[_EnvType, _ValueType, _ErrorType]', - ) -> 'RequiresContextFutureResult[_EnvType, _ValueType, _ErrorType]': + inner_value: 'RequiresContextResult[_ValueType, _ErrorType, _EnvType]', + ) -> 'RequiresContextFutureResult[_ValueType, _ErrorType, _EnvType]': """ Creates new container from ``RequiresContextResult`` as a unit value. @@ -1225,8 +1166,8 @@ def from_result_context( def from_ioresult_context( cls, inner_value: - 'RequiresContextIOResult[_EnvType, _ValueType, _ErrorType]', - ) -> 'RequiresContextFutureResult[_EnvType, _ValueType, _ErrorType]': + 'RequiresContextIOResult[_ValueType, _ErrorType, _EnvType]', + ) -> 'RequiresContextFutureResult[_ValueType, _ErrorType, _EnvType]': """ Creates new container from ``RequiresContextIOResult`` as a unit value. @@ -1258,7 +1199,7 @@ def from_ioresult_context( @classmethod def from_value( cls, inner_value: _FirstType, - ) -> 'RequiresContextFutureResult[NoDeps, _FirstType, Any]': + ) -> 'RequiresContextFutureResult[_FirstType, Any, NoDeps]': """ Creates new container with successful ``FutureResult`` as a unit value. @@ -1280,7 +1221,7 @@ def from_value( @classmethod def from_failure( cls, inner_value: _FirstType, - ) -> 'RequiresContextFutureResult[NoDeps, Any, _FirstType]': + ) -> 'RequiresContextFutureResult[Any, _FirstType, NoDeps]': """ Creates new container with failed ``FutureResult`` as a unit value. @@ -1304,9 +1245,9 @@ def from_iterable( cls, inner_value: Iterable[ - 'RequiresContextFutureResult[_EnvType, _ValueType, _ErrorType]', + 'RequiresContextFutureResult[_ValueType, _ErrorType, _EnvType]', ], - ) -> 'ReaderFutureResult[_EnvType, Sequence[_ValueType], _ErrorType]': + ) -> 'ReaderFutureResult[Sequence[_ValueType], _ErrorType, _EnvType]': """ Transforms an iterable of ``RequiresContextFutureResult`` containers. @@ -1351,7 +1292,7 @@ class ContextFutureResult(Immutable, Generic[_EnvType], metaclass=ABCMeta): __slots__ = () @classmethod - def ask(cls) -> RequiresContextFutureResult[_EnvType, _EnvType, Any]: + def ask(cls) -> RequiresContextFutureResult[_EnvType, Any, _EnvType]: """ Is used to get the current dependencies inside the call stack. @@ -1383,7 +1324,7 @@ def ask(cls) -> RequiresContextFutureResult[_EnvType, _EnvType, Any]: #: Alias for a popular case when ``Result`` has ``Exception`` as error type. RequiresContextFutureResultE = RequiresContextFutureResult[ - _EnvType, _ValueType, Exception, + _ValueType, Exception, _EnvType, ] #: Sometimes `RequiresContextFutureResult` is too long to type. @@ -1391,5 +1332,5 @@ def ask(cls) -> RequiresContextFutureResult[_EnvType, _EnvType, Any]: #: Alias to save you some typing. Uses ``Exception`` as error type. ReaderFutureResultE = RequiresContextFutureResult[ - _EnvType, _ValueType, Exception, + _ValueType, Exception, _EnvType, ] diff --git a/returns/context/requires_context_ioresult.py b/returns/context/requires_context_ioresult.py index 2d4f19cc3..48d5fc794 100644 --- a/returns/context/requires_context_ioresult.py +++ b/returns/context/requires_context_ioresult.py @@ -8,15 +8,17 @@ Iterable, Sequence, TypeVar, - Union, ) from typing_extensions import final from returns._generated.iterable import iterable from returns.context import NoDeps +from returns.interfaces import applicative, bindable, mappable, rescuable +from returns.interfaces.specific import result from returns.io import IO, IOFailure, IOResult, IOSuccess from returns.primitives.container import BaseContainer +from returns.primitives.hkt import Kind3, dekind from returns.primitives.types import Immutable from returns.result import Result @@ -40,7 +42,12 @@ @final class RequiresContextIOResult( BaseContainer, - Generic[_EnvType, _ValueType, _ErrorType], + Kind3['RequiresContextIOResult', _ValueType, _ErrorType, _EnvType], + mappable.Mappable3[_ValueType, _ErrorType, _EnvType], + bindable.Bindable3[_ValueType, _ErrorType, _EnvType], + applicative.Applicative3[_ValueType, _ErrorType, _EnvType], + rescuable.Rescuable3[_ValueType, _ErrorType, _EnvType], + result.ResultBased3[_ValueType, _ErrorType, _EnvType], ): """ The ``RequiresContextIOResult`` combinator. @@ -148,7 +155,7 @@ def __call__(self, deps: _EnvType) -> IOResult[_ValueType, _ErrorType]: >>> from returns.context import RequiresContextIOResult >>> from returns.io import IOSuccess - >>> def first(lg: bool) -> RequiresContextIOResult[float, int, str]: + >>> def first(lg: bool) -> RequiresContextIOResult[int, str, float]: ... # `deps` has `float` type here: ... return RequiresContextIOResult( ... lambda deps: IOSuccess(deps if lg else -deps), @@ -164,7 +171,7 @@ def __call__(self, deps: _EnvType) -> IOResult[_ValueType, _ErrorType]: def map( # noqa: WPS125 self, function: Callable[[_ValueType], _NewValueType], - ) -> 'RequiresContextIOResult[_EnvType, _NewValueType, _ErrorType]': + ) -> 'RequiresContextIOResult[_NewValueType, _ErrorType, _EnvType]': """ Composes successful container with a pure function. @@ -186,9 +193,13 @@ def map( # noqa: WPS125 def apply( self, - container: 'RequiresContextIOResult[' - '_EnvType, Callable[[_ValueType], _NewValueType], _ErrorType]', - ) -> 'RequiresContextIOResult[_EnvType, _NewValueType, _ErrorType]': + container: Kind3[ + 'RequiresContextIOResult', + Callable[[_ValueType], _NewValueType], + _ErrorType, + _EnvType, + ], + ) -> 'RequiresContextIOResult[_NewValueType, _ErrorType, _EnvType]': """ Calls a wrapped function in a container on this container. @@ -214,16 +225,21 @@ def apply( """ return RequiresContextIOResult( - lambda deps: self(deps).apply(container(deps)), + lambda deps: self(deps).apply(dekind(container)(deps)), ) def bind( self, function: Callable[ [_ValueType], - 'RequiresContextIOResult[_EnvType, _NewValueType, _ErrorType]', + Kind3[ + 'RequiresContextIOResult', + _NewValueType, + _ErrorType, + _EnvType, + ], ], - ) -> 'RequiresContextIOResult[_EnvType, _NewValueType, _ErrorType]': + ) -> 'RequiresContextIOResult[_NewValueType, _ErrorType, _EnvType]': """ Composes this container with a function returning the same type. @@ -232,7 +248,7 @@ def bind( >>> from returns.context import RequiresContextIOResult >>> from returns.io import IOSuccess, IOFailure - >>> def first(lg: bool) -> RequiresContextIOResult[float, int, int]: + >>> def first(lg: bool) -> RequiresContextIOResult[int, int, float]: ... # `deps` has `float` type here: ... return RequiresContextIOResult( ... lambda deps: IOSuccess(deps) if lg else IOFailure(-deps), @@ -240,7 +256,7 @@ def bind( >>> def second( ... number: int, - ... ) -> RequiresContextIOResult[float, str, int]: + ... ) -> RequiresContextIOResult[str, int, float]: ... # `deps` has `float` type here: ... return RequiresContextIOResult( ... lambda deps: IOSuccess('>=' if number >= deps else '<'), @@ -252,14 +268,16 @@ def bind( """ return RequiresContextIOResult( lambda deps: self(deps).bind( - lambda inner: function(inner)(deps), # type: ignore[misc] + lambda inner: dekind( # type: ignore[misc] + function(inner), + )(deps), ), ) def bind_result( self, function: Callable[[_ValueType], 'Result[_NewValueType, _ErrorType]'], - ) -> 'RequiresContextIOResult[_EnvType, _NewValueType, _ErrorType]': + ) -> 'RequiresContextIOResult[_NewValueType, _ErrorType, _EnvType]': """ Binds ``Result`` returning function to the current container. @@ -293,9 +311,9 @@ def bind_context( self, function: Callable[ [_ValueType], - 'RequiresContext[_EnvType, _NewValueType]', + 'RequiresContext[_NewValueType, _EnvType]', ], - ) -> 'RequiresContextIOResult[_EnvType, _NewValueType, _ErrorType]': + ) -> 'RequiresContextIOResult[_NewValueType, _ErrorType, _EnvType]': """ Binds ``RequiresContext`` returning function to current container. @@ -304,7 +322,7 @@ def bind_context( >>> from returns.context import RequiresContext >>> from returns.io import IOSuccess, IOFailure - >>> def function(arg: int) -> RequiresContext[str, int]: + >>> def function(arg: int) -> RequiresContext[int, str]: ... return RequiresContext(lambda deps: len(deps) + arg) >>> assert function(2)('abc') == 5 @@ -328,9 +346,9 @@ def bind_context_result( self, function: Callable[ [_ValueType], - 'RequiresContextResult[_EnvType, _NewValueType, _ErrorType]', + 'RequiresContextResult[_NewValueType, _ErrorType, _EnvType]', ], - ) -> 'RequiresContextIOResult[_EnvType, _NewValueType, _ErrorType]': + ) -> 'RequiresContextIOResult[_NewValueType, _ErrorType, _EnvType]': """ Binds ``RequiresContextResult`` returning function to the current one. @@ -340,7 +358,7 @@ def bind_context_result( >>> from returns.io import IOSuccess, IOFailure >>> from returns.result import Success, Failure - >>> def function(arg: int) -> RequiresContextResult[str, int, int]: + >>> def function(arg: int) -> RequiresContextResult[int, int, str]: ... if arg > 0: ... return RequiresContextResult( ... lambda deps: Success(len(deps) + arg), @@ -380,7 +398,7 @@ def bind_context_result( def bind_io( self, function: Callable[[_ValueType], IO[_NewValueType]], - ) -> 'RequiresContextIOResult[_EnvType, _NewValueType, _ErrorType]': + ) -> 'RequiresContextIOResult[_NewValueType, _ErrorType, _EnvType]': """ Binds ``IO`` returning function to the current container. @@ -408,7 +426,7 @@ def bind_io( def bind_ioresult( self, function: Callable[[_ValueType], IOResult[_NewValueType, _ErrorType]], - ) -> 'RequiresContextIOResult[_EnvType, _NewValueType, _ErrorType]': + ) -> 'RequiresContextIOResult[_NewValueType, _ErrorType, _EnvType]': """ Binds ``IOResult`` returning function to the current container. @@ -439,7 +457,7 @@ def bind_ioresult( def fix( self, function: Callable[[_ErrorType], _NewValueType], - ) -> 'RequiresContextIOResult[_EnvType, _NewValueType, _ErrorType]': + ) -> 'RequiresContextIOResult[_NewValueType, _ErrorType, _EnvType]': """ Composes failed container with a pure function. @@ -461,7 +479,7 @@ def fix( def alt( self, function: Callable[[_ErrorType], _NewErrorType], - ) -> 'RequiresContextIOResult[_EnvType, _ValueType, _NewErrorType]': + ) -> 'RequiresContextIOResult[_ValueType, _NewErrorType, _EnvType]': """ Composes failed container with a pure function. @@ -485,9 +503,14 @@ def rescue( self, function: Callable[ [_ErrorType], - 'RequiresContextIOResult[_EnvType, _ValueType, _NewErrorType]', + Kind3[ + 'RequiresContextIOResult', + _ValueType, + _NewErrorType, + _EnvType, + ], ], - ) -> 'RequiresContextIOResult[_EnvType, _ValueType, _NewErrorType]': + ) -> 'RequiresContextIOResult[_ValueType, _NewErrorType, _EnvType]': """ Composes this container with a function returning the same type. @@ -520,82 +543,14 @@ def rescue( """ return RequiresContextIOResult( lambda deps: self(deps).rescue( - lambda inner: function(inner)(deps), # type: ignore[misc] + lambda inner: function(inner)(deps), # type: ignore ), ) - def value_or( - self, default_value: _FirstType, - ) -> Callable[[_EnvType], IO[Union[_ValueType, _FirstType]]]: - """ - Returns a callable that either returns a success or default value. - - .. code:: python - - >>> from returns.context import RequiresContextIOResult - >>> from returns.io import IO - - >>> assert RequiresContextIOResult.from_value(1).value_or(2)( - ... RequiresContextIOResult.empty, - ... ) == IO(1) - - >>> assert RequiresContextIOResult.from_failure(1).value_or(2)( - ... RequiresContextIOResult.empty, - ... ) == IO(2) - - """ - return lambda deps: self(deps).value_or(default_value) - - def unwrap(self) -> Callable[[_EnvType], IO[_ValueType]]: - """ - Returns a callable that unwraps success value or raises exception. - - .. code:: pycon - - >>> from returns.context import RequiresContextIOResult - >>> from returns.io import IO - - >>> assert RequiresContextIOResult.from_value(1).unwrap()( - ... RequiresContextIOResult.empty, - ... ) == IO(1) - - >>> RequiresContextIOResult.from_failure(1).unwrap()( - ... RequiresContextIOResult.empty, - ... ) - Traceback (most recent call last): - ... - returns.primitives.exceptions.UnwrapFailedError - - """ - return lambda deps: self(deps).unwrap() - - def failure(self) -> Callable[[_EnvType], IO[_ErrorType]]: - """ - Returns a callable that unwraps failure value or raises exception. - - .. code:: pycon - - >>> from returns.context import RequiresContextIOResult - >>> from returns.io import IO - - >>> assert RequiresContextIOResult.from_failure(1).failure()( - ... RequiresContextIOResult.empty, - ... ) == IO(1) - - >>> RequiresContextIOResult.from_value(1).failure()( - ... RequiresContextIOResult.empty, - ... ) - Traceback (most recent call last): - ... - returns.primitives.exceptions.UnwrapFailedError - - """ - return lambda deps: self(deps).failure() - @classmethod def from_result( cls, inner_value: 'Result[_ValueType, _ErrorType]', - ) -> 'RequiresContextIOResult[NoDeps, _ValueType, _ErrorType]': + ) -> 'RequiresContextIOResult[_ValueType, _ErrorType, NoDeps]': """ Creates new container with ``Result`` as a unit value. @@ -623,7 +578,7 @@ def from_result( def from_io( cls, inner_value: IO[_NewValueType], - ) -> 'RequiresContextIOResult[NoDeps, _NewValueType, Any]': + ) -> 'RequiresContextIOResult[_NewValueType, Any, NoDeps]': """ Creates new container from successful ``IO`` value. @@ -645,7 +600,7 @@ def from_io( def from_failed_io( cls, inner_value: IO[_NewErrorType], - ) -> 'RequiresContextIOResult[NoDeps, Any, _NewErrorType]': + ) -> 'RequiresContextIOResult[Any, _NewErrorType, NoDeps]': """ Creates a new container from failed ``IO`` value. @@ -666,7 +621,7 @@ def from_failed_io( @classmethod def from_ioresult( cls, inner_value: IOResult[_ValueType, _ErrorType], - ) -> 'RequiresContextIOResult[NoDeps, _ValueType, _ErrorType]': + ) -> 'RequiresContextIOResult[_ValueType, _ErrorType, NoDeps]': """ Creates new container with ``IOResult`` as a unit value. @@ -691,8 +646,8 @@ def from_ioresult( def from_typecast( cls, inner_value: - 'RequiresContext[_EnvType, IOResult[_NewValueType, _NewErrorType]]', - ) -> 'RequiresContextIOResult[_EnvType, _NewValueType, _NewErrorType]': + 'RequiresContext[IOResult[_NewValueType, _NewErrorType], _EnvType]', + ) -> 'RequiresContextIOResult[_NewValueType, _NewErrorType, _EnvType]': """ You might end up with ``RequiresContext[IOResult]`` as a value. @@ -719,8 +674,8 @@ def from_typecast( @classmethod def from_context( - cls, inner_value: 'RequiresContext[_EnvType, _FirstType]', - ) -> 'RequiresContextIOResult[_EnvType, _FirstType, Any]': + cls, inner_value: 'RequiresContext[_FirstType, _EnvType]', + ) -> 'RequiresContextIOResult[_FirstType, Any, _EnvType]': """ Creates new container from ``RequiresContext`` as a success unit. @@ -740,8 +695,8 @@ def from_context( @classmethod def from_failed_context( - cls, inner_value: 'RequiresContext[_EnvType, _FirstType]', - ) -> 'RequiresContextIOResult[_EnvType, Any, _FirstType]': + cls, inner_value: 'RequiresContext[_FirstType, _EnvType]', + ) -> 'RequiresContextIOResult[Any, _FirstType, _EnvType]': """ Creates new container from ``RequiresContext`` as a failure unit. @@ -762,8 +717,8 @@ def from_failed_context( @classmethod def from_result_context( cls, - inner_value: 'RequiresContextResult[_EnvType, _ValueType, _ErrorType]', - ) -> 'RequiresContextIOResult[_EnvType, _ValueType, _ErrorType]': + inner_value: 'RequiresContextResult[_ValueType, _ErrorType, _EnvType]', + ) -> 'RequiresContextIOResult[_ValueType, _ErrorType, _EnvType]': """ Creates new container from ``RequiresContextResult`` as a unit value. @@ -787,8 +742,9 @@ def from_result_context( @classmethod def from_value( - cls, inner_value: _FirstType, - ) -> 'RequiresContextIOResult[NoDeps, _FirstType, Any]': + cls, + inner_value: _FirstType, + ) -> 'RequiresContextIOResult[_FirstType, Any, NoDeps]': """ Creates new container with ``IOSuccess(inner_value)`` as a unit value. @@ -806,8 +762,9 @@ def from_value( @classmethod def from_failure( - cls, inner_value: _FirstType, - ) -> 'RequiresContextIOResult[NoDeps, Any, _FirstType]': + cls, + inner_value: _FirstType, + ) -> 'RequiresContextIOResult[Any, _FirstType, NoDeps]': """ Creates new container with ``IOFailure(inner_value)`` as a unit value. @@ -828,9 +785,9 @@ def from_iterable( cls, inner_value: Iterable[ - 'RequiresContextIOResult[_EnvType, _ValueType, _ErrorType]', + 'RequiresContextIOResult[_ValueType, _ErrorType, _EnvType]', ], - ) -> 'RequiresContextIOResult[_EnvType, Sequence[_ValueType], _ErrorType]': + ) -> 'RequiresContextIOResult[Sequence[_ValueType], _ErrorType, _EnvType]': """ Transforms an iterable of ``RequiresContextIOResult`` containers. @@ -873,7 +830,7 @@ class ContextIOResult(Immutable, Generic[_EnvType], metaclass=ABCMeta): __slots__ = () @classmethod - def ask(cls) -> RequiresContextIOResult[_EnvType, _EnvType, Any]: + def ask(cls) -> RequiresContextIOResult[_EnvType, Any, _EnvType]: """ Is used to get the current dependencies inside the call stack. @@ -900,11 +857,11 @@ def ask(cls) -> RequiresContextIOResult[_EnvType, _EnvType, Any]: #: Alias for a popular case when ``Result`` has ``Exception`` as error type. RequiresContextIOResultE = RequiresContextIOResult[ - _EnvType, _ValueType, Exception, + _ValueType, Exception, _EnvType, ] #: Alias to save you some typing. Uses original name from Haskell. -ReaderIOResult = RequiresContextIOResult[_EnvType, _ValueType, _ErrorType] +ReaderIOResult = RequiresContextIOResult #: Alias to save you some typing. Uses ``Exception`` as error type. -ReaderIOResultE = RequiresContextIOResult[_EnvType, _ValueType, Exception] +ReaderIOResultE = RequiresContextIOResult[_ValueType, Exception, _EnvType] diff --git a/returns/context/requires_context_result.py b/returns/context/requires_context_result.py index ec44c6f18..99c764919 100644 --- a/returns/context/requires_context_result.py +++ b/returns/context/requires_context_result.py @@ -8,14 +8,16 @@ Iterable, Sequence, TypeVar, - Union, ) from typing_extensions import final from returns._generated.iterable import iterable from returns.context import NoDeps +from returns.interfaces import applicative, bindable, mappable, rescuable +from returns.interfaces.specific import result from returns.primitives.container import BaseContainer +from returns.primitives.hkt import Kind3, dekind from returns.primitives.types import Immutable from returns.result import Failure, Result, Success @@ -38,7 +40,12 @@ @final class RequiresContextResult( BaseContainer, - Generic[_EnvType, _ValueType, _ErrorType], + Kind3['RequiresContextResult', _ValueType, _ErrorType, _EnvType], + mappable.Mappable3[_ValueType, _ErrorType, _EnvType], + bindable.Bindable3[_ValueType, _ErrorType, _EnvType], + applicative.Applicative3[_ValueType, _ErrorType, _EnvType], + rescuable.Rescuable3[_ValueType, _ErrorType, _EnvType], + result.ResultBased3[_ValueType, _ErrorType, _EnvType], ): """ The ``RequiresContextResult`` combinator. @@ -137,7 +144,7 @@ def __call__(self, deps: _EnvType) -> Result[_ValueType, _ErrorType]: >>> from returns.context import RequiresContextResult >>> from returns.result import Success - >>> def first(lg: bool) -> RequiresContextResult[float, int, str]: + >>> def first(lg: bool) -> RequiresContextResult[int, str, float]: ... # `deps` has `float` type here: ... return RequiresContextResult( ... lambda deps: Success(deps if lg else -deps), @@ -153,7 +160,7 @@ def __call__(self, deps: _EnvType) -> Result[_ValueType, _ErrorType]: def map( # noqa: WPS125 self, function: Callable[[_ValueType], _NewValueType], - ) -> 'RequiresContextResult[_EnvType, _NewValueType, _ErrorType]': + ) -> 'RequiresContextResult[_NewValueType, _ErrorType, _EnvType]': """ Composes successful container with a pure function. @@ -175,9 +182,13 @@ def map( # noqa: WPS125 def apply( self, - container: 'RequiresContextResult[' - '_EnvType, Callable[[_ValueType], _NewValueType], _ErrorType]', - ) -> 'RequiresContextResult[_EnvType, _NewValueType, _ErrorType]': + container: Kind3[ + 'RequiresContextResult', + Callable[[_ValueType], _NewValueType], + _ErrorType, + _EnvType, + ], + ) -> 'RequiresContextResult[_NewValueType, _ErrorType, _EnvType]': """ Calls a wrapped function in a container on this container. @@ -203,16 +214,21 @@ def apply( """ return RequiresContextResult( - lambda deps: self(deps).apply(container(deps)), + lambda deps: self(deps).apply(dekind(container)(deps)), ) def bind( self, function: Callable[ [_ValueType], - 'RequiresContextResult[_EnvType, _NewValueType, _ErrorType]', + Kind3[ + 'RequiresContextResult', + _NewValueType, + _ErrorType, + _EnvType, + ], ], - ) -> 'RequiresContextResult[_EnvType, _NewValueType, _ErrorType]': + ) -> 'RequiresContextResult[_NewValueType, _ErrorType, _EnvType]': """ Composes this container with a function returning the same type. @@ -221,7 +237,7 @@ def bind( >>> from returns.context import RequiresContextResult >>> from returns.result import Success, Failure - >>> def first(lg: bool) -> RequiresContextResult[float, int, int]: + >>> def first(lg: bool) -> RequiresContextResult[int, int, float]: ... # `deps` has `float` type here: ... return RequiresContextResult( ... lambda deps: Success(deps) if lg else Failure(-deps), @@ -229,7 +245,7 @@ def bind( >>> def second( ... number: int, - ... ) -> RequiresContextResult[float, str, int]: + ... ) -> RequiresContextResult[str, int, float]: ... # `deps` has `float` type here: ... return RequiresContextResult( ... lambda deps: Success('>=' if number >= deps else '<'), @@ -248,7 +264,7 @@ def bind( def bind_result( self, function: Callable[[_ValueType], Result[_NewValueType, _ErrorType]], - ) -> 'RequiresContextResult[_EnvType, _NewValueType, _ErrorType]': + ) -> 'RequiresContextResult[_NewValueType, _ErrorType, _EnvType]': """ Binds ``Result`` returning function to current container. @@ -257,7 +273,7 @@ def bind_result( >>> from returns.context import RequiresContextResult >>> from returns.result import Success, Failure, Result - >>> def function(num: int) -> Result[int, str]: + >>> def function(num: int) -> Result[str, int]: ... return Success(num + 1) if num > 0 else Failure('<0') >>> assert RequiresContextResult.from_value(1).bind_result( @@ -279,9 +295,9 @@ def bind_context( self, function: Callable[ [_ValueType], - 'RequiresContext[_EnvType, _NewValueType]', + 'RequiresContext[_NewValueType, _EnvType]', ], - ) -> 'RequiresContextResult[_EnvType, _NewValueType, _ErrorType]': + ) -> 'RequiresContextResult[_NewValueType, _ErrorType, _EnvType]': """ Binds ``RequiresContext`` returning function to current container. @@ -290,7 +306,7 @@ def bind_context( >>> from returns.context import RequiresContext >>> from returns.result import Success, Failure - >>> def function(arg: int) -> RequiresContext[str, int]: + >>> def function(arg: int) -> RequiresContext[int, str]: ... return RequiresContext(lambda deps: len(deps) + arg) >>> assert function(2)('abc') == 5 @@ -312,7 +328,7 @@ def bind_context( def fix( self, function: Callable[[_ErrorType], _NewValueType], - ) -> 'RequiresContextResult[_EnvType, _NewValueType, _ErrorType]': + ) -> 'RequiresContextResult[_NewValueType, _ErrorType, _EnvType]': """ Composes failed container with a pure function. @@ -334,7 +350,7 @@ def fix( def alt( self, function: Callable[[_ErrorType], _NewErrorType], - ) -> 'RequiresContextResult[_EnvType, _ValueType, _NewErrorType]': + ) -> 'RequiresContextResult[_ValueType, _NewErrorType, _EnvType]': """ Composes failed container with a pure function. @@ -358,9 +374,14 @@ def rescue( self, function: Callable[ [_ErrorType], - 'RequiresContextResult[_EnvType, _ValueType, _NewErrorType]', + Kind3[ + 'RequiresContextResult', + _ValueType, + _NewErrorType, + _EnvType, + ], ], - ) -> 'RequiresContextResult[_EnvType, _ValueType, _NewErrorType]': + ) -> 'RequiresContextResult[_ValueType, _NewErrorType, _EnvType]': """ Composes this container with a function returning the same type. @@ -395,77 +416,10 @@ def rescue( ), ) - def value_or( - self, default_value: _FirstType, - ) -> Callable[[_EnvType], Union[_ValueType, _FirstType]]: - """ - Returns a callable that either returns a success or default value. - - .. code:: python - - >>> from returns.context import RequiresContextResult - - >>> assert RequiresContextResult.from_value(1).value_or(2)( - ... RequiresContextResult.empty, - ... ) == 1 - - >>> assert RequiresContextResult.from_failure(1).value_or(2)( - ... RequiresContextResult.empty, - ... ) == 2 - - """ - return lambda deps: self(deps).value_or(default_value) - - def unwrap(self) -> Callable[[_EnvType], _ValueType]: - """ - Returns a callable that unwraps success value or raises exception. - - .. code:: pycon - - >>> from returns.context import RequiresContextResult - >>> from returns.result import Success, Failure - - >>> assert RequiresContextResult( - ... lambda _: Success(1), - ... ).unwrap()(RequiresContextResult.empty) == 1 - - >>> RequiresContextResult( - ... lambda _: Failure(1), - ... ).unwrap()(RequiresContextResult.empty) - Traceback (most recent call last): - ... - returns.primitives.exceptions.UnwrapFailedError - - """ - return lambda deps: self(deps).unwrap() - - def failure(self) -> Callable[[_EnvType], _ErrorType]: - """ - Returns a callable that unwraps failure value or raises exception. - - .. code:: pycon - - >>> from returns.context import RequiresContextResult - >>> from returns.result import Success, Failure - - >>> assert RequiresContextResult( - ... lambda _: Failure(1), - ... ).failure()(RequiresContextResult.empty) == 1 - - >>> RequiresContextResult( - ... lambda _: Success(1), - ... ).failure()(RequiresContextResult.empty) - Traceback (most recent call last): - ... - returns.primitives.exceptions.UnwrapFailedError - - """ - return lambda deps: self(deps).failure() - @classmethod def from_result( cls, inner_value: Result[_ValueType, _ErrorType], - ) -> 'RequiresContextResult[NoDeps, _ValueType, _ErrorType]': + ) -> 'RequiresContextResult[_ValueType, _ErrorType, NoDeps]': """ Creates new container with ``Result`` as a unit value. @@ -490,8 +444,8 @@ def from_result( def from_typecast( cls, inner_value: - 'RequiresContext[_EnvType, Result[_NewValueType, _NewErrorType]]', - ) -> 'RequiresContextResult[_EnvType, _NewValueType, _NewErrorType]': + 'RequiresContext[Result[_NewValueType, _NewErrorType], _EnvType]', + ) -> 'RequiresContextResult[_NewValueType, _NewErrorType, _EnvType]': """ You might end up with ``RequiresContext[Result[...]]`` as a value. @@ -518,8 +472,8 @@ def from_typecast( @classmethod def from_context( - cls, inner_value: 'RequiresContext[_EnvType, _FirstType]', - ) -> 'RequiresContextResult[_EnvType, _FirstType, Any]': + cls, inner_value: 'RequiresContext[_FirstType, _EnvType]', + ) -> 'RequiresContextResult[_FirstType, Any, _EnvType]': """ Creates new container from ``RequiresContext`` as a success unit. @@ -536,8 +490,8 @@ def from_context( @classmethod def from_failed_context( - cls, inner_value: 'RequiresContext[_EnvType, _FirstType]', - ) -> 'RequiresContextResult[_EnvType, Any, _FirstType]': + cls, inner_value: 'RequiresContext[_FirstType, _EnvType]', + ) -> 'RequiresContextResult[Any, _FirstType, _EnvType]': """ Creates new container from ``RequiresContext`` as a failure unit. @@ -555,7 +509,7 @@ def from_failed_context( @classmethod def from_value( cls, inner_value: _FirstType, - ) -> 'RequiresContextResult[NoDeps, _FirstType, Any]': + ) -> 'RequiresContextResult[_FirstType, Any, NoDeps]': """ Creates new container with ``Success(inner_value)`` as a unit value. @@ -571,7 +525,7 @@ def from_value( @classmethod def from_failure( cls, inner_value: _FirstType, - ) -> 'RequiresContextResult[NoDeps, Any, _FirstType]': + ) -> 'RequiresContextResult[Any, _FirstType, NoDeps]': """ Creates new container with ``Failure(inner_value)`` as a unit value. @@ -588,8 +542,8 @@ def from_failure( def from_iterable( cls, inner_value: - Iterable['RequiresContextResult[_EnvType, _ValueType, _ErrorType]'], - ) -> 'RequiresContextResult[_EnvType, Sequence[_ValueType], _ErrorType]': + Iterable['RequiresContextResult[_ValueType, _ErrorType, _EnvType]'], + ) -> 'RequiresContextResult[Sequence[_ValueType], _ErrorType, _EnvType]': """ Transforms an iterable of ``RequiresContextResult`` containers. @@ -630,7 +584,7 @@ class ContextResult(Immutable, Generic[_EnvType], metaclass=ABCMeta): __slots__ = () @classmethod - def ask(cls) -> RequiresContextResult[_EnvType, _EnvType, Any]: + def ask(cls) -> RequiresContextResult[_EnvType, Any, _EnvType]: """ Is used to get the current dependencies inside the call stack. @@ -657,11 +611,11 @@ def ask(cls) -> RequiresContextResult[_EnvType, _EnvType, Any]: #: Alias for a popular case when ``Result`` has ``Exception`` as error type. RequiresContextResultE = RequiresContextResult[ - _EnvType, _ValueType, Exception, + _ValueType, Exception, _EnvType, ] #: Alias to save you some typing. Uses original name from Haskell. -ReaderResult = RequiresContextResult[_EnvType, _ValueType, _ErrorType] +ReaderResult = RequiresContextResult #: Alias to save you some typing. Has ``Exception`` as error type. -ReaderResultE = RequiresContextResult[_EnvType, _ValueType, Exception] +ReaderResultE = RequiresContextResult[_ValueType, Exception, _EnvType] diff --git a/returns/contrib/mypy/_consts.py b/returns/contrib/mypy/_consts.py new file mode 100644 index 000000000..6697e450a --- /dev/null +++ b/returns/contrib/mypy/_consts.py @@ -0,0 +1,34 @@ +from typing_extensions import Final + +# Constant fullnames for typechecking +# =================================== + +#: Set of full names of our decorators. +TYPED_DECORATORS: Final = frozenset(( + 'returns.result.safe', + 'returns.io.impure', + 'returns.io.impure_safe', + 'returns.maybe.maybe', + 'returns.future.future', + 'returns.future.asyncify', + 'returns.future.future_safe', + 'returns.functions.not_', +)) + +#: Used for typed ``partial`` function. +TYPED_PARTIAL_FUNCTION: Final = 'returns.curry.partial' + +#: Used for typed ``curry`` decorator. +TYPED_CURRY_FUNCTION: Final = 'returns.curry.curry' + +#: Used for typed ``flow`` call. +TYPED_FLOW_FUNCTION: Final = 'returns._generated.pipeline.flow._flow' + +#: Used for typed ``pipe`` call. +TYPED_PIPE_FUNCTION: Final = 'returns._generated.pipeline.pipe._pipe' +TYPED_PIPE_METHOD: Final = 'returns._generated.pipeline.pipe._Pipe.__call__' + +#: Used for HKT emulation. +TYPED_KIND_DEKIND: Final = 'returns.primitives.hkt.dekind' +TYPED_KIND_DEBOUND: Final = 'returns.primitives.hkt.debound' +TYPED_KIND_KINDED: Final = 'returns.primitives.hkt.Kinded.__call__' diff --git a/returns/contrib/mypy/_features/flow.py b/returns/contrib/mypy/_features/flow.py index 76860b69d..13e9351d8 100644 --- a/returns/contrib/mypy/_features/flow.py +++ b/returns/contrib/mypy/_features/flow.py @@ -33,14 +33,11 @@ def analyze(ctx: FunctionContext) -> MypyType: """ if not ctx.arg_types[0]: return ctx.default_return_type - if not ctx.arg_types[1]: # We do require to pass `*functions` arg. - ctx.api.fail('Too few arguments for "_flow"', ctx.context) - return ctx.default_return_type return PipelineInference( ctx.arg_types[0][0], ).from_callable_sequence( - ctx.arg_types[1], - ctx.arg_kinds[1], + [arg_type[0] for arg_type in ctx.arg_types[1:] if arg_type], + [arg_kind[0] for arg_kind in ctx.arg_kinds[1:] if arg_kind], ctx, ) diff --git a/returns/contrib/mypy/_features/kind.py b/returns/contrib/mypy/_features/kind.py new file mode 100644 index 000000000..79c6b8e8a --- /dev/null +++ b/returns/contrib/mypy/_features/kind.py @@ -0,0 +1,145 @@ +from enum import Enum, unique +from typing import cast + +from mypy.plugin import FunctionContext, MethodContext, MethodSigContext +from mypy.typeops import erase_to_bound +from mypy.types import AnyType, CallableType, Instance, TupleType +from mypy.types import Type as MypyType +from mypy.types import TypeOfAny, TypeVarType, get_proper_type + +# TODO: probably we can validate `KindN[]` creation during `get_analtype` + + +def dekind(ctx: FunctionContext) -> MypyType: + """ + Infers real type behind ``Kind`` form. + + Basically, it turns ``Kind[IO, int]`` into ``IO[int]``. + The only limitation is that it works with + only ``Instance`` type in the first type argument position. + + So, ``dekind(Kind[T, int])`` will fail. + """ + kind = get_proper_type(ctx.arg_types[0][0]) + correct_args = ( + isinstance(kind, Instance) and + isinstance(kind.args[0], Instance) + ) + + if not correct_args: + ctx.api.fail(_KindErrors.dekind_not_instance, ctx.context) + return AnyType(TypeOfAny.from_error) + + assert isinstance(kind, Instance) # mypy requires these lines + assert isinstance(kind.args[0], Instance) + return kind.args[0].copy_modified( + args=kind.args[1:len(kind.args[0].args) + 1], + ) + + +def debound(ctx: FunctionContext) -> MypyType: + """ + Analyzes the proper return type of ``debound`` function. + + Uses the ``upper_bound`` of ``TypeVar`` to infer the type of a ``Kind``. + + Here's a quick example: + + .. code:: python + + from typing import TypeVar + from returns.primitives.hkt import Kind1, debound + from returns.interfaces import Bindable1 + + B = TypeVar('B', bound=Bindable1) + + x: Kind1[B, int] + instance, rebound = debound(x) + reveal_type(instance) # Revealed type: 'Bindable[int]' + + See :func:`returns.primitives.hkt.debound` for more information. + + """ + if not isinstance(ctx.default_return_type, TupleType): + return AnyType(TypeOfAny.from_error) + if not ctx.arg_types or not ctx.arg_types[0][0]: + return AnyType(TypeOfAny.from_error) + + kind = cast(Instance, ctx.arg_types[0][0]) + typevar = kind.args[0] + if not isinstance(typevar, TypeVarType): + ctx.api.fail(_KindErrors.debound_not_typevar, ctx.context) + return AnyType(TypeOfAny.from_error) + + bound = get_proper_type(erase_to_bound(typevar)) + if not isinstance(bound, Instance): + ctx.api.fail(_KindErrors.debound_not_typevar, ctx.context) + return AnyType(TypeOfAny.from_error) + + instance = bound.copy_modified(args=kind.args[1:]) + return ctx.default_return_type.copy_modified( + items=[instance, ctx.default_return_type.items[1]], + ) + + +def kinded_signature(ctx: MethodSigContext) -> CallableType: + """ + Returns the internal function wrapped as ``Kinded[def]``. + + Works for ``Kinded`` class when ``__call__`` magic method is used. + See :class:`returns.primitives.hkt.Kinded` for more information. + """ + assert isinstance(ctx.type, Instance) + assert isinstance(ctx.type.args[0], CallableType) + return ctx.type.args[0] + + +def kinded_method(ctx: MethodContext) -> MypyType: + """ + Reveals the correct return type of ``Kinded.__call__`` method. + + Turns ``KindN[I, t1, t2, t3]`` into ``I[t1, t2, t3]``. + + Also strips unused type arguments for ``KindN``, so: + - ``KindN[IO, int, , ]`` will be ``IO[int]`` + - ``KindN[Result, int, str, ]`` will be ``Result[int, str]`` + + It also processes nested ``KindN`` with recursive strategy. + + See :class:`returns.primitives.hkt.Kinded` for more information. + """ + return _process_kinded_type(ctx.default_return_type) + + +@unique # noqa: WPS600 +class _KindErrors(str, Enum): # noqa: WPS600 + """Represents a set of possible errors we can throw during typechecking.""" + + dekind_not_instance = ( + 'dekind must be used with Instance as the first type argument' + ) + debound_not_typevar = ( + 'debound must be used with bound TypeVar as the first type argument' + ) + + +def _process_kinded_type(kind: MypyType) -> MypyType: + """Recursively process all type arguments in a kind.""" + kind = get_proper_type(kind) + if not isinstance(kind, Instance) or not kind.args: + return kind + + real_type = kind.args[0] + if isinstance(real_type, TypeVarType): + return erase_to_bound(real_type) + + real_type = get_proper_type(real_type) + if isinstance(real_type, Instance): + return real_type.copy_modified(args=[ + # Let's check if there are any nested `KindN[]` instance, + # if so, it would be dekinded into a regular type following + # the same rules: + _process_kinded_type(type_arg) + for type_arg in kind.args[1:len(real_type.args) + 1] + ]) + return kind diff --git a/returns/contrib/mypy/_features/pipe.py b/returns/contrib/mypy/_features/pipe.py index 34881b147..2a77f7c28 100644 --- a/returns/contrib/mypy/_features/pipe.py +++ b/returns/contrib/mypy/_features/pipe.py @@ -36,7 +36,6 @@ >>> assert pipeline(0) == 'not bigger' # `signature and `infer` again """ - from typing import Callable, Tuple from mypy.checker import detach_callable @@ -50,36 +49,6 @@ from returns.contrib.mypy._typeops.inference import PipelineInference -def _get_first_arg_type(case: CallableType) -> MypyType: - """Function might not have args at all.""" - if case.arg_types: - return case.arg_types[0] - return AnyType(TypeOfAny.implementation_artifact) - - -def _unify_type( - function: FunctionLike, - fetch_type: Callable[[CallableType], MypyType], -) -> MypyType: - return UnionType.make_union([ - fetch_type(case) - for case in function.items() - ]) - - -def _get_pipeline_def( - ctx: FunctionContext, -) -> Tuple[MypyType, MypyType]: - first_step = ctx.arg_types[0][0] - last_step = ctx.arg_types[0][-1] - - if isinstance(first_step, (Instance, TypeType)): - first_step = safe_translate_to_function(ctx.arg_types[0][0], ctx) - if isinstance(last_step, (Instance, TypeType)): - last_step = safe_translate_to_function(ctx.arg_types[0][-1], ctx) - return first_step, last_step - - def analyze(ctx: FunctionContext) -> MypyType: """This hook helps when we create the pipeline from sequence of funcs.""" if not isinstance(ctx.default_return_type, Instance): @@ -125,3 +94,33 @@ def infer(ctx: MethodContext) -> MypyType: def signature(ctx: MethodSigContext) -> CallableType: """Helps to fix generics in method signature.""" return detach_callable(ctx.default_signature) + + +def _get_first_arg_type(case: CallableType) -> MypyType: + """Function might not have args at all.""" + if case.arg_types: + return case.arg_types[0] + return AnyType(TypeOfAny.implementation_artifact) + + +def _unify_type( + function: FunctionLike, + fetch_type: Callable[[CallableType], MypyType], +) -> MypyType: + return UnionType.make_union([ + fetch_type(case) + for case in function.items() + ]) + + +def _get_pipeline_def( + ctx: FunctionContext, +) -> Tuple[MypyType, MypyType]: + first_step = ctx.arg_types[0][0] + last_step = ctx.arg_types[0][-1] + + if isinstance(first_step, (Instance, TypeType)): + first_step = safe_translate_to_function(ctx.arg_types[0][0], ctx) + if isinstance(last_step, (Instance, TypeType)): + last_step = safe_translate_to_function(ctx.arg_types[0][-1], ctx) + return first_step, last_step diff --git a/returns/contrib/mypy/_features/pointfree.py b/returns/contrib/mypy/_features/pointfree.py deleted file mode 100644 index 0403feda0..000000000 --- a/returns/contrib/mypy/_features/pointfree.py +++ /dev/null @@ -1,25 +0,0 @@ -from mypy.checkmember import analyze_member_access -from mypy.plugin import FunctionContext -from mypy.types import Type as MypyType - - -def analyze(ctx: FunctionContext) -> MypyType: - """ - Analyzes several pointfree functions. - - Removes intermediate Protocol instances. - """ - callee = ctx.default_return_type - checker = ctx.api.expr_checker # type: ignore - return analyze_member_access( - '__call__', - callee, - ctx.context, - is_lvalue=False, - is_super=False, - is_operator=True, - msg=checker.msg, - original_type=callee, - chk=checker.chk, - in_literal_context=checker.is_literal_context(), - ) diff --git a/returns/contrib/mypy/returns_plugin.py b/returns/contrib/mypy/returns_plugin.py index 584a5a029..607afa365 100644 --- a/returns/contrib/mypy/returns_plugin.py +++ b/returns/contrib/mypy/returns_plugin.py @@ -10,77 +10,23 @@ We use ``pytest-mypy-plugins`` to test that it works correctly, see: https://github.com/mkurnikov/pytest-mypy-plugins """ - from typing import Callable, ClassVar, Mapping, Optional, Type from mypy.plugin import FunctionContext, MethodContext, MethodSigContext, Plugin from mypy.types import CallableType from mypy.types import Type as MypyType -from typing_extensions import Final, final +from typing_extensions import final +from returns.contrib.mypy import _consts from returns.contrib.mypy._features import ( curry, decorators, flow, + kind, partial, pipe, - pointfree, ) -# Constant fullnames for typechecking -# =================================== - -#: Set of full names of our decorators. -_TYPED_DECORATORS: Final = frozenset(( - 'returns.result.safe', - 'returns.io.impure', - 'returns.io.impure_safe', - 'returns.maybe.maybe', - 'returns.future.future', - 'returns.future.asyncify', - 'returns.future.future_safe', - 'returns.functions.not_', -)) - -#: Used for cases when we return a protocol overloaded based on a return type. -_TYPED_PROTOCOL_OVERLOADED: Final = frozenset(( - # Pointfree functions: - 'returns._generated.pointfree.map._map', - 'returns._generated.pointfree.alt._alt', - 'returns._generated.pointfree.fix._fix', - - 'returns._generated.pointfree.bind_result._bind_result', - 'returns._generated.pointfree.bind_io._bind_io', - 'returns._generated.pointfree.bind_ioresult._bind_ioresult', - 'returns._generated.pointfree.bind_future._bind_future', - 'returns._generated.pointfree.bind_async_future._bind_async_future', - 'returns._generated.pointfree.bind_future_result._bind_future_result', - ( - 'returns._generated.pointfree.bind_async_future_result.' + - '_bind_async_future_result' - ), - 'returns._generated.pointfree.bind_context._bind_context', - 'returns._generated.pointfree.bind_context_result._bind_context_result', - 'returns._generated.pointfree.bind_context_ioresult._bind_context_ioresult', - 'returns._generated.pointfree.bind_awaitable._bind_awaitable', - - 'returns._generated.pointfree.value_or._value_or', -)) - -#: Used for typed ``partial`` function. -_TYPED_PARTIAL_FUNCTION: Final = 'returns.curry.partial' - -#: Used for typed ``curry`` decorator. -_TYPED_CURRY_FUNCTION: Final = 'returns.curry.curry' - -#: Used for typed ``flow`` call. -_TYPED_FLOW_FUNCTION: Final = 'returns._generated.pipeline.flow._flow' - -#: Used for typed ``pipe`` call. -_TYPED_PIPE_FUNCTION: Final = 'returns._generated.pipeline.pipe._pipe' -_TYPED_PIPE_METHOD: Final = 'returns._generated.pipeline.pipe._Pipe.__call__' - - # Type aliases # ============ @@ -102,20 +48,23 @@ class _ReturnsPlugin(Plugin): """Our main plugin to dispatch different callbacks to specific features.""" _function_hook_plugins: ClassVar[Mapping[str, _FunctionCallback]] = { - _TYPED_PARTIAL_FUNCTION: partial.analyze, - _TYPED_CURRY_FUNCTION: curry.analyze, - _TYPED_FLOW_FUNCTION: flow.analyze, - _TYPED_PIPE_FUNCTION: pipe.analyze, - **dict.fromkeys(_TYPED_PROTOCOL_OVERLOADED, pointfree.analyze), - **dict.fromkeys(_TYPED_DECORATORS, decorators.analyze), + _consts.TYPED_PARTIAL_FUNCTION: partial.analyze, + _consts.TYPED_CURRY_FUNCTION: curry.analyze, + _consts.TYPED_FLOW_FUNCTION: flow.analyze, + _consts.TYPED_PIPE_FUNCTION: pipe.analyze, + _consts.TYPED_KIND_DEKIND: kind.dekind, + _consts.TYPED_KIND_DEBOUND: kind.debound, + **dict.fromkeys(_consts.TYPED_DECORATORS, decorators.analyze), } - _method_hook_plugins: ClassVar[Mapping[str, _MethodCallback]] = { - _TYPED_PIPE_METHOD: pipe.infer, + _method_sig_hook_plugins: ClassVar[Mapping[str, _MethodSigCallback]] = { + _consts.TYPED_PIPE_METHOD: pipe.signature, + _consts.TYPED_KIND_KINDED: kind.kinded_signature, } - _method_sig_hook_plugins: ClassVar[Mapping[str, _MethodSigCallback]] = { - _TYPED_PIPE_METHOD: pipe.signature, + _method_hook_plugins: ClassVar[Mapping[str, _MethodCallback]] = { + _consts.TYPED_PIPE_METHOD: pipe.infer, + _consts.TYPED_KIND_KINDED: kind.kinded_method, } def get_function_hook( @@ -133,13 +82,6 @@ def get_function_hook( """ return self._function_hook_plugins.get(fullname) - def get_method_hook( - self, - fullname: str, - ) -> Optional[_MethodCallback]: - """Called for method return types from ``mypy``.""" - return self._method_hook_plugins.get(fullname) - def get_method_signature_hook( self, fullname: str, @@ -147,6 +89,13 @@ def get_method_signature_hook( """Called for method signature from ``mypy``.""" return self._method_sig_hook_plugins.get(fullname) + def get_method_hook( + self, + fullname: str, + ) -> Optional[_MethodCallback]: + """Called for method return types from ``mypy``.""" + return self._method_hook_plugins.get(fullname) + def plugin(version: str) -> Type[Plugin]: """Plugin's public API and entrypoint.""" diff --git a/returns/contrib/pytest/plugin.py b/returns/contrib/pytest/plugin.py index 60c361617..e8cce31d9 100644 --- a/returns/contrib/pytest/plugin.py +++ b/returns/contrib/pytest/plugin.py @@ -69,9 +69,9 @@ def containers_to_patch(cls) -> tuple: RequiresContextIOResult, RequiresContextResult, ) + from returns.future import FutureResult from returns.io import _IOFailure, _IOSuccess from returns.result import _Failure, _Success - from returns.future import FutureResult return ( _Success, diff --git a/returns/future.py b/returns/future.py index c76a610a6..cd375c796 100644 --- a/returns/future.py +++ b/returns/future.py @@ -6,7 +6,6 @@ ClassVar, Coroutine, Generator, - Generic, Iterable, Sequence, Type, @@ -18,8 +17,11 @@ from returns._generated.futures import _future, _future_result from returns._generated.iterable import iterable +from returns.interfaces import applicative, bindable, mappable, rescuable +from returns.interfaces.specific import result from returns.io import IO, IOResult from returns.primitives.container import BaseContainer +from returns.primitives.hkt import Kind1, Kind2, dekind from returns.result import Failure, Result, Success # Definitions: @@ -56,7 +58,13 @@ async def async_identity(instance: _FirstType) -> _FirstType: # ====== @final -class Future(BaseContainer, Generic[_ValueType]): +class Future( + BaseContainer, + Kind1['Future', _ValueType], + mappable.Mappable1[_ValueType], + bindable.Bindable1[_ValueType], + applicative.Applicative1[_ValueType], +): """ Container to easily compose ``async`` functions. @@ -186,7 +194,7 @@ def map( # noqa: WPS125 def apply( self, - container: 'Future[Callable[[_ValueType], _NewValueType]]', + container: Kind1['Future', Callable[[_ValueType], _NewValueType]], ) -> 'Future[_NewValueType]': """ Calls a wrapped function in a container on this container. @@ -206,11 +214,11 @@ def apply( ... ) == IO('1b') """ - return Future(_future.async_apply(container, self._inner_value)) + return Future(_future.async_apply(dekind(container), self._inner_value)) def bind( self, - function: Callable[[_ValueType], 'Future[_NewValueType]'], + function: Callable[[_ValueType], Kind1['Future', _NewValueType]], ) -> 'Future[_NewValueType]': """ Applies 'function' to the result of a previous calculation. @@ -482,7 +490,15 @@ async def decorator(*args, **kwargs): # ============ @final -class FutureResult(BaseContainer, Generic[_ValueType, _ErrorType]): +class FutureResult( + BaseContainer, + Kind2['FutureResult', _ValueType, _ErrorType], + mappable.Mappable2[_ValueType, _ErrorType], + bindable.Bindable2[_ValueType, _ErrorType], + applicative.Applicative2[_ValueType, _ErrorType], + rescuable.Rescuable2[_ValueType, _ErrorType], + result.ResultBased2[_ValueType, _ErrorType], +): """ Container to easily compose ``async`` functions. @@ -628,8 +644,11 @@ def map( # noqa: WPS125 def apply( self, - container: - 'FutureResult[Callable[[_ValueType], _NewValueType], _ErrorType]', + container: Kind2[ + 'FutureResult', + Callable[[_ValueType], _NewValueType], + _ErrorType, + ], ) -> 'FutureResult[_NewValueType, _ErrorType]': """ Calls a wrapped function in a container on this container. @@ -662,14 +681,14 @@ def apply( """ return FutureResult(_future_result.async_apply( - container, self._inner_value, + dekind(container), self._inner_value, )) def bind( self, function: Callable[ [_ValueType], - 'FutureResult[_NewValueType, _ErrorType]', + Kind2['FutureResult', _NewValueType, _ErrorType], ], ) -> 'FutureResult[_NewValueType, _ErrorType]': """ @@ -1007,7 +1026,7 @@ def rescue( self, function: Callable[ [_ErrorType], - 'FutureResult[_ValueType, _NewErrorType]', + Kind2['FutureResult', _ValueType, _NewErrorType], ], ) -> 'FutureResult[_ValueType, _NewErrorType]': """ @@ -1034,67 +1053,6 @@ def rescue( function, self._inner_value, )) - def value_or( - self, - default_value: _NewValueType, - ) -> Awaitable[IO[Union[_ValueType, _NewValueType]]]: - """ - Get value or default value. - - .. code:: python - - >>> import anyio - >>> from returns.future import FutureResult - >>> from returns.io import IO - - >>> async def main(): - ... first = await FutureResult.from_value(1).value_or(2) - ... second = await FutureResult.from_failure(3).value_or(4) - ... return first, second - - >>> assert anyio.run(main) == (IO(1), IO(4)) - - """ - return _future_result.async_value_or(self, default_value) - - def unwrap(self) -> Awaitable[IO[_ValueType]]: - """ - Get value or raise exception. - - .. code:: pycon - - >>> import anyio - >>> from returns.future import FutureResult - >>> from returns.io import IO - >>> assert anyio.run(FutureResult.from_value(1).unwrap) == IO(1) - - >>> anyio.run(FutureResult.from_failure(1).unwrap) - Traceback (most recent call last): - ... - returns.primitives.exceptions.UnwrapFailedError - - """ - return _future_result.async_unwrap(self) - - def failure(self) -> Awaitable[IO[_ErrorType]]: - """ - Get failed value or raise exception. - - .. code:: pycon - - >>> import anyio - >>> from returns.future import FutureResult - >>> from returns.io import IO - >>> assert anyio.run(FutureResult.from_failure(1).failure) == IO(1) - - >>> anyio.run(FutureResult.from_value(1).failure) - Traceback (most recent call last): - ... - returns.primitives.exceptions.UnwrapFailedError - - """ - return _future_result.async_failure(self) - @classmethod def from_typecast( cls, diff --git a/returns/_generated/pointfree/__init__.py b/returns/interfaces/__init__.py similarity index 100% rename from returns/_generated/pointfree/__init__.py rename to returns/interfaces/__init__.py diff --git a/returns/interfaces/applicative.py b/returns/interfaces/applicative.py new file mode 100644 index 000000000..b687d2273 --- /dev/null +++ b/returns/interfaces/applicative.py @@ -0,0 +1,51 @@ +from abc import abstractmethod +from typing import Callable, Generic, NoReturn, Type, TypeVar + +from returns.primitives.hkt import KindN + +_FirstType = TypeVar('_FirstType') +_SecondType = TypeVar('_SecondType') +_ThirdType = TypeVar('_ThirdType') +_UpdatedType = TypeVar('_UpdatedType') +_ApplicativeType = TypeVar('_ApplicativeType', bound='ApplicativeN') + + +class ApplicativeN(Generic[_FirstType, _SecondType, _ThirdType]): + """ + Allows to create unit containers from raw values and to apply wrapped funcs. + + See also: + https://en.wikipedia.org/wiki/Applicative_functor + http://learnyouahaskell.com/functors-applicative-functors-and-monoids + + """ + + @abstractmethod + def apply( + self: _ApplicativeType, + container: KindN[ + _ApplicativeType, + Callable[[_FirstType], _UpdatedType], + _SecondType, + _ThirdType, + ], + ) -> KindN[_ApplicativeType, _UpdatedType, _SecondType, _ThirdType]: + """Allows to apply a wrapped function over a container.""" + + @classmethod + @abstractmethod + def from_value( + cls: Type[_ApplicativeType], # noqa: N805 + inner_value: _FirstType, + ) -> KindN[_ApplicativeType, _FirstType, _SecondType, _ThirdType]: + """Unit method to create new containers from any raw value.""" + + +#: Type alias for kinds with one type argument. +Applicative1 = ApplicativeN[_FirstType, NoReturn, NoReturn] + +#: Type alias for kinds with two type arguments. +Applicative2 = ApplicativeN[_FirstType, _SecondType, NoReturn] + +#: Type alias for kinds with three type arguments. +Applicative3 = ApplicativeN[_FirstType, _SecondType, _ThirdType] diff --git a/returns/interfaces/bindable.py b/returns/interfaces/bindable.py new file mode 100644 index 000000000..6dda7a94c --- /dev/null +++ b/returns/interfaces/bindable.py @@ -0,0 +1,47 @@ +from abc import abstractmethod +from typing import Callable, Generic, NoReturn, TypeVar + +from returns.primitives.hkt import KindN + +_FirstType = TypeVar('_FirstType') +_SecondType = TypeVar('_SecondType') +_ThirdType = TypeVar('_ThirdType') +_UpdatedType = TypeVar('_UpdatedType') +_BindableType = TypeVar('_BindableType', bound='BindableN') + + +class BindableN(Generic[_FirstType, _SecondType, _ThirdType]): + """ + Represents a "context" in which calculations can be executed. + + ``Bindable`` allows you to bind together + a series of calculations while maintaining + the context of that specific container. + + In contrast to :class:`returns.interfaces.rescuable.RescuableN`, + works with the first type value. + """ + + @abstractmethod + def bind( + self: _BindableType, + function: Callable[ + [_FirstType], + KindN[_BindableType, _UpdatedType, _SecondType, _ThirdType], + ], + ) -> KindN[_BindableType, _UpdatedType, _SecondType, _ThirdType]: + """ + Applies 'function' to the result of a previous calculation. + + And returns a new container. + """ + + +#: Type alias for kinds with one type argument. +Bindable1 = BindableN[_FirstType, NoReturn, NoReturn] + +#: Type alias for kinds with two type arguments. +Bindable2 = BindableN[_FirstType, _SecondType, NoReturn] + +#: Type alias for kinds with three type arguments. +Bindable3 = BindableN[_FirstType, _SecondType, _ThirdType] diff --git a/returns/interfaces/mappable.py b/returns/interfaces/mappable.py new file mode 100644 index 000000000..6f228d88a --- /dev/null +++ b/returns/interfaces/mappable.py @@ -0,0 +1,38 @@ +from abc import abstractmethod +from typing import Callable, Generic, NoReturn, TypeVar + +from returns.primitives.hkt import KindN + +_FirstType = TypeVar('_FirstType') +_SecondType = TypeVar('_SecondType') +_ThirdType = TypeVar('_ThirdType') +_UpdatedType = TypeVar('_UpdatedType') +_MappableType = TypeVar('_MappableType', bound='MappableN') + + +class MappableN(Generic[_FirstType, _SecondType, _ThirdType]): + """ + Allows to chain wrapped values in containers with regular functions. + + Behaves like a functor. + + See also: + https://en.wikipedia.org/wiki/Functor + """ + + @abstractmethod # noqa: WPS125 + def map( # noqa: WPS125 + self: _MappableType, + function: Callable[[_FirstType], _UpdatedType], + ) -> KindN[_MappableType, _UpdatedType, _SecondType, _ThirdType]: + """Allows to run a pure function over a container.""" + + +#: Type alias for kinds with one type argument. +Mappable1 = MappableN[_FirstType, NoReturn, NoReturn] + +#: Type alias for kinds with two type arguments. +Mappable2 = MappableN[_FirstType, _SecondType, NoReturn] + +#: Type alias for kinds with three type arguments. +Mappable3 = MappableN[_FirstType, _SecondType, _ThirdType] diff --git a/returns/interfaces/rescuable.py b/returns/interfaces/rescuable.py new file mode 100644 index 000000000..30494cdf6 --- /dev/null +++ b/returns/interfaces/rescuable.py @@ -0,0 +1,47 @@ +from abc import abstractmethod +from typing import Callable, Generic, NoReturn, TypeVar + +from returns.primitives.hkt import KindN + +_FirstType = TypeVar('_FirstType') +_SecondType = TypeVar('_SecondType') +_ThirdType = TypeVar('_ThirdType') +_UpdatedType = TypeVar('_UpdatedType') +_RescuableType = TypeVar('_RescuableType', bound='RescuableN') + + +class RescuableN(Generic[_FirstType, _SecondType, _ThirdType]): + """ + Represents a "context" in which calculations can be executed. + + ``Rescueable`` allows you to bind together + a series of calculations while maintaining + the context of that specific container. + + In contrast to :class:`returns.interfaces.bindable.BinbdaleN`, + works with the second type value. + """ + + @abstractmethod + def rescue( + self: _RescuableType, + function: Callable[ + [_SecondType], + KindN[_RescuableType, _FirstType, _UpdatedType, _ThirdType], + ], + ) -> KindN[_RescuableType, _FirstType, _UpdatedType, _ThirdType]: + """ + Applies 'function' to the result of a previous calculation. + + And returns a new container. + """ + + +#: Type alias for kinds with one type argument. +Rescuable1 = RescuableN[_FirstType, NoReturn, NoReturn] + +#: Type alias for kinds with two type arguments. +Rescuable2 = RescuableN[_FirstType, _SecondType, NoReturn] + +#: Type alias for kinds with three type arguments. +Rescuable3 = RescuableN[_FirstType, _SecondType, _ThirdType] diff --git a/returns/interfaces/specific/__init__.py b/returns/interfaces/specific/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/returns/interfaces/specific/result.py b/returns/interfaces/specific/result.py new file mode 100644 index 000000000..19304ad63 --- /dev/null +++ b/returns/interfaces/specific/result.py @@ -0,0 +1,57 @@ +from abc import abstractmethod +from typing import TYPE_CHECKING, Callable, Generic, NoReturn, Type, TypeVar + +from returns.primitives.hkt import KindN + +if TYPE_CHECKING: + from returns.result import Result # noqa: WPS433 + +_FirstType = TypeVar('_FirstType', contravariant=True) +_SecondType = TypeVar('_SecondType', contravariant=True) +_ThirdType = TypeVar('_ThirdType', contravariant=True) +_UpdatedType = TypeVar('_UpdatedType', covariant=True) +_ResultBasedType = TypeVar('_ResultBasedType', bound='ResultBasedN') + + +class ResultBasedN(Generic[_FirstType, _SecondType, _ThirdType]): + """ + Allows to create unit containers from raw values and to apply wrapped funcs. + + See also: + https://en.wikipedia.org/wiki/ResultBased_functor + http://learnyouahaskell.com/functors-ResultBased-functors-and-monoids + + """ + + @abstractmethod + def bind_result( + self: _ResultBasedType, + function: Callable[[_FirstType], 'Result[_UpdatedType, _SecondType]'], + ) -> KindN[_ResultBasedType, _UpdatedType, _SecondType, _ThirdType]: + """Allows to apply a wrapped function over a container.""" + + @classmethod + @abstractmethod + def from_result( + cls: Type[_ResultBasedType], # noqa: N805 + inner_value: 'Result[_FirstType, _SecondType]', + ) -> KindN[_ResultBasedType, _FirstType, _SecondType, _ThirdType]: + """Unit method to create new containers from any raw value.""" + + @classmethod + @abstractmethod + def from_failure( + cls: Type[_ResultBasedType], # noqa: N805 + inner_value: _SecondType, + ) -> KindN[_ResultBasedType, _FirstType, _SecondType, _ThirdType]: + """Unit method to create new containers from any raw value.""" + + +#: Type alias for kinds with one type argument. +ResultBased1 = ResultBasedN[_FirstType, NoReturn, NoReturn] + +#: Type alias for kinds with two type arguments. +ResultBased2 = ResultBasedN[_FirstType, _SecondType, NoReturn] + +#: Type alias for kinds with three type arguments. +ResultBased3 = ResultBasedN[_FirstType, _SecondType, _ThirdType] diff --git a/returns/interfaces/unwrappable.py b/returns/interfaces/unwrappable.py new file mode 100644 index 000000000..478f5e3a9 --- /dev/null +++ b/returns/interfaces/unwrappable.py @@ -0,0 +1,44 @@ +from abc import abstractmethod +from typing import Generic, TypeVar + +_FirstType = TypeVar('_FirstType') +_SecondType = TypeVar('_SecondType') +_UnwrappableType = TypeVar('_UnwrappableType', bound='Unwrappable') + + +class Unwrappable(Generic[_FirstType, _SecondType]): + """ + Represents containers that can unwrap and return its wrapped value. + + There are no aliases or ``UnwrappableN`` for ``Unwrappable`` interface. + Because it always uses two and just two types. + """ + + @abstractmethod + def unwrap(self: _UnwrappableType) -> _FirstType: + """ + Custom magic method to unwrap inner value from container. + + Should be redefined for ones that actually have values. + And for ones that raise an exception for no values. + + .. note:: + As a part of the contract, failed ``unwrap`` calls + must raise :class:`returns.primitives.excetion.UnwrapFailedError` + exception. + + This method is the opposite of :meth:`~Unwrapable.failure`. + """ + + @abstractmethod + def failure(self: _UnwrappableType) -> _SecondType: + """ + Custom magic method to unwrap inner value from the failed container. + + .. note:: + As a part of the contract, failed ``failure`` calls + must raise :class:`returns.primitives.excetion.UnwrapFailedError` + exception. + + This method is the opposite of :meth:`~Unwrapable.unwrap`. + """ diff --git a/returns/io.py b/returns/io.py index 2389f9b50..23f54b3bf 100644 --- a/returns/io.py +++ b/returns/io.py @@ -1,11 +1,10 @@ -from abc import ABCMeta +from abc import ABCMeta, abstractmethod from functools import wraps from inspect import FrameInfo from typing import ( Any, Callable, ClassVar, - Generic, Iterable, List, Optional, @@ -18,7 +17,16 @@ from typing_extensions import final from returns._generated.iterable import iterable +from returns.interfaces import ( + applicative, + bindable, + mappable, + rescuable, + unwrappable, +) +from returns.interfaces.specific import result from returns.primitives.container import BaseContainer +from returns.primitives.hkt import Kind1, Kind2, dekind from returns.result import Failure, Result, Success _ValueType = TypeVar('_ValueType', covariant=True) @@ -33,7 +41,13 @@ _SecondType = TypeVar('_SecondType') -class IO(BaseContainer, Generic[_ValueType]): +class IO( + BaseContainer, + Kind1['IO', _ValueType], + mappable.Mappable1[_ValueType], + bindable.Bindable1[_ValueType], + applicative.Applicative1[_ValueType], +): """ Explicit container for impure function results. @@ -68,8 +82,7 @@ def __init__(self, inner_value: _ValueType) -> None: .. code:: python >>> from returns.io import IO - >>> str(IO(1)) - '' + >>> assert str(IO(1)) == '' """ super().__init__(inner_value) @@ -98,7 +111,7 @@ def map( # noqa: WPS125 def apply( self, - container: 'IO[Callable[[_ValueType], _NewValueType]]', + container: Kind1['IO', Callable[[_ValueType], _NewValueType]], ) -> 'IO[_NewValueType]': """ Calls a wrapped function in a container on this container. @@ -122,10 +135,11 @@ def apply( >>> assert IO('b').apply(IO('a').apply(IO(appliable))) == IO('ab') """ - return self.map(container._inner_value) # noqa: WPS437 + return self.map(dekind(container)._inner_value) # noqa: WPS437 def bind( - self, function: Callable[[_ValueType], 'IO[_NewValueType]'], + self, + function: Callable[[_ValueType], Kind1['IO', _NewValueType]], ) -> 'IO[_NewValueType]': """ Applies 'function' to the result of a previous calculation. @@ -141,7 +155,7 @@ def bind( >>> assert IO('a').bind(bindable) == IO('ab') """ - return function(self._inner_value) + return dekind(function(self._inner_value)) @classmethod def from_value(cls, inner_value: _NewValueType) -> 'IO[_NewValueType]': @@ -155,7 +169,7 @@ def from_value(cls, inner_value: _NewValueType) -> 'IO[_NewValueType]': >>> from returns.io import IO >>> assert IO(1) == IO.from_value(1) - Part of the :class:`returns.primitives.interfaces.Applicative` + Part of the :class:`returns.interfaces.applicative.Applicative` protocol. """ return IO(inner_value) @@ -237,7 +251,13 @@ def decorator(*args, **kwargs): class IOResult( BaseContainer, - Generic[_ValueType, _ErrorType], + Kind2['IOResult', _ValueType, _ErrorType], + mappable.Mappable2[_ValueType, _ErrorType], + bindable.Bindable2[_ValueType, _ErrorType], + applicative.Applicative2[_ValueType, _ErrorType], + unwrappable.Unwrappable[IO[_ValueType], IO[_ErrorType]], + rescuable.Rescuable2[_ValueType, _ErrorType], + result.ResultBased2[_ValueType, _ErrorType], metaclass=ABCMeta, ): """ @@ -284,11 +304,10 @@ class IOResult( See also: https://github.com/gcanti/fp-ts/blob/master/docs/modules/IOEither.ts.md - Implementation ~~~~~~~~~~~~~~ This class contains all the methods that can be delegated to ``Result``. - But, some methods have ``raise NotImplementedError`` which means + But, some methods are ``@abstractmethod`` which means that we have to use special :class:`~_IOSuccess` and :class:`~_IOFailure` implementation details to correctly handle these callbacks. @@ -296,8 +315,6 @@ class IOResult( """ - outer: ClassVar[Type[IO]] = IO - _inner_value: Result[_ValueType, _ErrorType] # These two are required for projects like `classes`: @@ -317,7 +334,7 @@ def __init__(self, inner_value: Result[_ValueType, _ErrorType]) -> None: @property def trace(self) -> Optional[List[FrameInfo]]: - """Returns a list with stack trace when :func:`~Failure` was called.""" + """Returns a stack trace when :func:`~IOFailure` was called.""" return self._inner_value.trace def map( # noqa: WPS125 @@ -336,8 +353,11 @@ def map( # noqa: WPS125 def apply( self, - container: - 'IOResult[Callable[[_ValueType], _NewValueType], _ErrorType]', + container: Kind2[ + 'IOResult', + Callable[[_ValueType], _NewValueType], + _ErrorType, + ], ) -> 'IOResult[_NewValueType, _ErrorType]': """ Calls a wrapped function in a container on this container. @@ -369,11 +389,12 @@ def apply( ) return container # type: ignore + @abstractmethod def bind( self, function: Callable[ [_ValueType], - 'IOResult[_NewValueType, _ErrorType]', + Kind2['IOResult', _NewValueType, _ErrorType], ], ) -> 'IOResult[_NewValueType, _ErrorType]': """ @@ -392,13 +413,13 @@ def bind( >>> assert IOFailure('a').bind(bindable) == IOFailure('a') """ - raise NotImplementedError + @abstractmethod def bind_result( self, function: Callable[ [_ValueType], - 'Result[_NewValueType, _ErrorType]', + Result[_NewValueType, _ErrorType], ], ) -> 'IOResult[_NewValueType, _ErrorType]': """ @@ -423,8 +444,8 @@ def bind_result( >>> assert IOFailure('a').bind_result(bindable) == IOFailure('a') """ - raise NotImplementedError + @abstractmethod def bind_io( self, function: Callable[[_ValueType], IO[_NewValueType]], @@ -446,7 +467,6 @@ def bind_io( >>> assert IOFailure('a').bind_io(bindable) == IOFailure('a') """ - raise NotImplementedError def unify( self, @@ -505,11 +525,12 @@ def alt( """ return self.from_result(self._inner_value.alt(function)) + @abstractmethod def rescue( self, function: Callable[ [_ErrorType], - 'IOResult[_ValueType, _NewErrorType]', + Kind2['IOResult', _ValueType, _NewErrorType], ], ) -> 'IOResult[_ValueType, _NewErrorType]': """ @@ -528,7 +549,6 @@ def rescue( >>> assert IOSuccess('a').rescue(rescuable) == IOSuccess('a') """ - raise NotImplementedError def value_or( self, @@ -661,7 +681,6 @@ def from_value( """ One more value to create success unit values. - This is a part of :class:`returns.primitives.interfaces.Unitable`. It is useful as a united way to create a new value from any container. .. code:: python @@ -682,7 +701,6 @@ def from_failure( """ One more value to create failure unit values. - This is a part of :class:`returns.primitives.interfaces.Unitable`. It is useful as a united way to create a new value from any container. .. code:: python @@ -893,7 +911,6 @@ def impure_safe( and :func:`returns.result.safe` decorators. Requires our :ref:`mypy plugin `. - """ @wraps(function) def decorator(*args, **kwargs): diff --git a/returns/maybe.py b/returns/maybe.py index 84ba52302..d376c805a 100644 --- a/returns/maybe.py +++ b/returns/maybe.py @@ -1,10 +1,9 @@ -from abc import ABCMeta +from abc import ABCMeta, abstractmethod from functools import wraps from typing import ( Any, Callable, ClassVar, - Generic, Iterable, NoReturn, Optional, @@ -17,8 +16,10 @@ from typing_extensions import final from returns._generated.iterable import iterable +from returns.interfaces import applicative, bindable, mappable, unwrappable from returns.primitives.container import BaseContainer from returns.primitives.exceptions import UnwrapFailedError +from returns.primitives.hkt import Kind1 # Definitions: _ValueType = TypeVar('_ValueType', covariant=True) @@ -31,7 +32,11 @@ class Maybe( BaseContainer, - Generic[_ValueType], + Kind1['Maybe', _ValueType], + mappable.Mappable1[_ValueType], + bindable.Bindable1[_ValueType], + applicative.Applicative1[_ValueType], + unwrappable.Unwrappable[_ValueType, None], metaclass=ABCMeta, ): """ @@ -55,6 +60,7 @@ class Maybe( #: Failure type that is used to represent the failed computation. failure_type: ClassVar[Type['_Nothing']] + @abstractmethod # noqa: WPS125 def map( # noqa: WPS125 self, function: Callable[[_ValueType], Optional[_NewValueType]], @@ -72,11 +78,11 @@ def map( # noqa: WPS125 >>> assert Nothing.map(mappable) == Nothing """ - raise NotImplementedError + @abstractmethod def apply( self, - function: 'Maybe[Callable[[_ValueType], _NewValueType]]', + function: Kind1['Maybe', Callable[[_ValueType], _NewValueType]], ) -> 'Maybe[_NewValueType]': """ Calls a wrapped function in a container on this container. @@ -94,11 +100,11 @@ def apply( >>> assert Nothing.apply(Nothing) == Nothing """ - raise NotImplementedError + @abstractmethod def bind( self, - function: Callable[[_ValueType], 'Maybe[_NewValueType]'], + function: Callable[[_ValueType], Kind1['Maybe', _NewValueType]], ) -> 'Maybe[_NewValueType]': """ Composes successful container with a function that returns a container. @@ -113,7 +119,6 @@ def bind( >>> assert Nothing.bind(bindable) == Nothing """ - raise NotImplementedError def value_or( self, @@ -129,8 +134,8 @@ def value_or( >>> assert Nothing.value_or(1) == 1 """ - raise NotImplementedError + @abstractmethod def or_else_call( self, function: Callable[[], _NewValueType], @@ -165,8 +170,8 @@ def or_else_call( ValueError: Nothing! """ - raise NotImplementedError + @abstractmethod def unwrap(self) -> _ValueType: """ Get value from successful container or raise exception for failed one. @@ -182,8 +187,8 @@ def unwrap(self) -> _ValueType: returns.primitives.exceptions.UnwrapFailedError """ - raise NotImplementedError + @abstractmethod def failure(self) -> None: """ Get failed value from failed container or raise exception from success. @@ -199,12 +204,11 @@ def failure(self) -> None: returns.primitives.exceptions.UnwrapFailedError """ - raise NotImplementedError @classmethod def from_value( - cls, inner_value: Optional[_ValueType], - ) -> 'Maybe[_ValueType]': + cls, inner_value: Optional[_NewValueType], + ) -> 'Maybe[_NewValueType]': """ Creates new instance of ``Maybe`` container based on a value. diff --git a/returns/methods/__init__.py b/returns/methods/__init__.py new file mode 100644 index 000000000..306a48f2f --- /dev/null +++ b/returns/methods/__init__.py @@ -0,0 +1,5 @@ +from returns.methods.apply import apply as apply +from returns.methods.bind import bind as bind +from returns.methods.bind_result import bind_result as bind_result +from returns.methods.map import map_ as map_ +from returns.methods.rescue import rescue as rescue diff --git a/returns/methods/apply.py b/returns/methods/apply.py new file mode 100644 index 000000000..08cae5aa6 --- /dev/null +++ b/returns/methods/apply.py @@ -0,0 +1,59 @@ +from typing import Callable, TypeVar + +from returns.interfaces.applicative import ApplicativeN +from returns.primitives.hkt import KindN, debound, kinded + +_FirstType = TypeVar('_FirstType') +_SecondType = TypeVar('_SecondType') +_ThirdType = TypeVar('_ThirdType') +_UpdatedType = TypeVar('_UpdatedType') + +_ApplicativeKind = TypeVar('_ApplicativeKind', bound=ApplicativeN) + + +def internal_apply( + container: KindN[_ApplicativeKind, _FirstType, _SecondType, _ThirdType], + other: KindN[ + _ApplicativeKind, + Callable[[_FirstType], _UpdatedType], + _SecondType, + _ThirdType, + ], +) -> KindN[_ApplicativeKind, _UpdatedType, _SecondType, _ThirdType]: + """ + Calls a wrapped function in a container on the first container. + + It is not marked as ``@kinded``, because this function is intended + to be used inside a kinded context: + like in :func:`returns.pointfree.apply.apply`. + It returns ``KindN[]`` instance, not a real type. + + If you wish to use the user-facing ``apply`` + that infers the return type correctly, + use :func:`~bind` function instead. + + .. code:: python + + >>> from returns.methods.apply import internal_apply, apply + >>> from returns.maybe import Some, Nothing + + >>> def example(argument: int) -> int: + ... return argument + 1 + + >>> applied = apply(Some(1), Some(example)) + >>> assert applied == internal_apply(Some(1), Some(example)) == Some(2) + + >>> applied = apply(Nothing, Some(example)) + >>> assert applied == internal_apply(Nothing, Some(example)) == Nothing + + Note, that this function works for all containers with ``.apply`` method. + See :class:`returns.primitives.interfaces.Applicative.ApplicativeN` + for more info. + + """ + new_instance, rebound = debound(container) + return rebound(new_instance.apply(other)) + + +#: Kinded version of :func:`~internal_apply`, use it to infer real return type. +apply = kinded(internal_apply) diff --git a/returns/methods/bind.py b/returns/methods/bind.py new file mode 100644 index 000000000..efb8b2a37 --- /dev/null +++ b/returns/methods/bind.py @@ -0,0 +1,56 @@ +from typing import Callable, TypeVar + +from returns.interfaces.bindable import BindableN +from returns.primitives.hkt import KindN, debound, kinded + +_FirstType = TypeVar('_FirstType') +_SecondType = TypeVar('_SecondType') +_ThirdType = TypeVar('_ThirdType') +_UpdatedType = TypeVar('_UpdatedType') + +_BindableKind = TypeVar('_BindableKind', bound=BindableN) + + +def internal_bind( + container: KindN[_BindableKind, _FirstType, _SecondType, _ThirdType], + function: Callable[ + [_FirstType], + KindN[_BindableKind, _UpdatedType, _SecondType, _ThirdType], + ], +) -> KindN[_BindableKind, _UpdatedType, _SecondType, _ThirdType]: + """ + Bind a function over a container. + + It is not marked as ``@kinded``, because this function is intended + to be used inside a kinded context: + like in :func:`returns.pointfree.bind.bind`. + It returns ``KindN[]`` instance, not a real type. + + If you wish to use the user-facing ``bind`` + that infers the return type correctly, + use :func:`~bind` function instead. + + .. code:: python + + >>> from returns.methods.bind import internal_bind, bind + >>> from returns.maybe import Maybe, Some, Nothing + + >>> def example(argument: int) -> Maybe[int]: + ... return Some(argument + 1) + + >>> bound = bind(Some(1), example) + >>> assert bound == internal_bind(Some(1), example) == Some(2) + + >>> bound = bind(Nothing, example) + >>> assert bound == internal_bind(Nothing, example) == Nothing + + Note, that this function works for all containers with ``.bind`` method. + See :class:`returns.primitives.interfaces.bindable.BindableN` for more info. + + """ + new_instance, rebound = debound(container) + return rebound(new_instance.bind(function)) + + +#: Kinded version of :func:`~internal_bind`, use it to infer real return type. +bind = kinded(internal_bind) diff --git a/returns/methods/bind_result.py b/returns/methods/bind_result.py new file mode 100644 index 000000000..bb2647e25 --- /dev/null +++ b/returns/methods/bind_result.py @@ -0,0 +1,57 @@ +from typing import TYPE_CHECKING, Callable, TypeVar + +from returns.interfaces.specific.result import ResultBasedN +from returns.primitives.hkt import KindN, debound, kinded + +if TYPE_CHECKING: + from returns.result import Result # noqa: WPS433 + +_FirstType = TypeVar('_FirstType') +_SecondType = TypeVar('_SecondType') +_ThirdType = TypeVar('_ThirdType') +_UpdatedType = TypeVar('_UpdatedType') + +_ResultBasedKind = TypeVar('_ResultBasedKind', bound=ResultBasedN) + + +def internal_bind_result( + container: KindN[_ResultBasedKind, _FirstType, _SecondType, _ThirdType], + function: Callable[[_FirstType], 'Result[_UpdatedType, _SecondType]'], +) -> KindN[_ResultBasedKind, _UpdatedType, _SecondType, _ThirdType]: + """ + Bind a ``Result`` returning function over a container. + + It is not marked as ``@kinded``, because this function is intended + to be used inside a kinded context: + like in :func:`returns.pointfree.bind.bind`. + It returns ``KindN[]`` instance, not a real type. + + If you wish to use the user-facing ``bind_result`` + that infers the return type correctly, + use :func:`~bind_result` function instead. + + .. code:: python + + >>> from returns.methods.bind_result import bind_result + >>> from returns.result import Result, Success + >>> from returns.io import IOSuccess, IOFailure + + >>> def example(argument: int) -> Result[int, str]: + ... return Success(argument + 1) + + >>> assert bind_result(IOSuccess(1), example) == IOSuccess(2) + >>> assert bind_result(IOFailure('a'), example) == IOFailure('a') + + Note, that this function works + for all containers with ``.bind_result`` method. + See :class:`returns.primitives.interfaces.specific.result.ResultBasedN` + for more info. + + """ + new_instance, rebound = debound(container) + return rebound(new_instance.bind_result(function)) + + +#: Kinded version of :func:`~internal_bind_result`, +#: use it to infer real return type. +bind_result = kinded(internal_bind_result) diff --git a/returns/methods/map.py b/returns/methods/map.py new file mode 100644 index 000000000..1dfac5ecd --- /dev/null +++ b/returns/methods/map.py @@ -0,0 +1,53 @@ +from typing import Callable, TypeVar + +from returns.interfaces.mappable import MappableN +from returns.primitives.hkt import KindN, debound, kinded + +_FirstType = TypeVar('_FirstType', contravariant=True) +_SecondType = TypeVar('_SecondType') +_ThirdType = TypeVar('_ThirdType', contravariant=True) +_UpdatedType = TypeVar('_UpdatedType', covariant=True) + +_MappableKind = TypeVar('_MappableKind', bound=MappableN) + + +def internal_map( + container: KindN[_MappableKind, _FirstType, _SecondType, _ThirdType], + function: Callable[[_FirstType], _UpdatedType], +) -> KindN[_MappableKind, _UpdatedType, _SecondType, _ThirdType]: + """ + Maps a function over a container. + + It is not marked as ``@kinded``, because this function is intended + to be used inside a kinded context: + like in :func:`returns.pointfree.map.map_`. + It returns ``KindN[]`` instance, not a real type. + + If you wish to use the user-facing ``map`` + that infers the return type correctly, + use :func:`~map_` function instead. + + .. code:: python + + >>> from returns.methods.map import internal_map, map_ + >>> from returns.maybe import Some, Nothing + + >>> def example(argument: int) -> int: + ... return argument + 1 + + >>> bound = map_(Some(1), example) + >>> assert bound == internal_map(Some(1), example) == Some(2) + + >>> bound = map_(Nothing, example) + >>> assert bound == internal_map(Nothing, example) == Nothing + + Note, that this function works for all containers with ``.map`` method. + See :class:`returns.primitives.interfaces.mappable.MappableN` for more info. + + """ + new_instance, rebound = debound(container) + return rebound(new_instance.map(function)) + + +#: Kinded version of :func:`~internal_map`, use it to infer real return type. +map_ = kinded(internal_map) diff --git a/returns/methods/rescue.py b/returns/methods/rescue.py new file mode 100644 index 000000000..9649925d2 --- /dev/null +++ b/returns/methods/rescue.py @@ -0,0 +1,54 @@ +from typing import Callable, TypeVar + +from returns.interfaces.rescuable import RescuableN +from returns.primitives.hkt import KindN, debound, kinded + +_FirstType = TypeVar('_FirstType') +_SecondType = TypeVar('_SecondType') +_ThirdType = TypeVar('_ThirdType') +_UpdatedType = TypeVar('_UpdatedType') + +_RescuableKind = TypeVar('_RescuableKind', bound=RescuableN) + + +def internal_rescue( + container: KindN[_RescuableKind, _FirstType, _SecondType, _ThirdType], + function: Callable[ + [_SecondType], + KindN[_RescuableKind, _FirstType, _UpdatedType, _ThirdType], + ], +) -> KindN[_RescuableKind, _FirstType, _UpdatedType, _ThirdType]: + """ + Bind a function over a container. Works for the second type argument. + + It is not marked as ``@kinded``, because this function is intended + to be used inside a kinded context: + like in :func:`returns.pointfree.bind.bind`. + It returns ``KindN[]`` instance, not a real type. + + If you wish to use the user-facing ``rescue`` + that infers the return type correctly, + use :func:`~rescue` function instead. + + .. code:: python + + >>> from returns.methods.rescue import rescue + >>> from returns.result import Result, Success, Failure + + >>> def example(argument: int) -> Result[str, int]: + ... return Failure(argument + 1) + + >>> assert rescue(Failure(1), example) == Failure(2) + >>> assert rescue(Success('a'), example) == Success('a') + + Note, that this function works for all containers with ``.rescue`` method. + See :class:`returns.primitives.interfaces.rescuable.RescuableN` + for more info. + + """ + new_instance, rebound = debound(container) + return rebound(new_instance.rescue(function)) + + +#: Kinded version of :func:`~internal_rescue`, use it to infer real return type. +rescue = kinded(internal_rescue) diff --git a/returns/pipeline.py b/returns/pipeline.py index 426fe7a15..c304e080c 100644 --- a/returns/pipeline.py +++ b/returns/pipeline.py @@ -1,19 +1,13 @@ from typing import ClassVar -from typing_extensions import Protocol - from returns._generated.pipeline.flow import _flow as flow from returns._generated.pipeline.managed import _managed as managed from returns._generated.pipeline.pipe import _pipe as pipe +from returns.interfaces.unwrappable import Unwrappable +from returns.primitives.exceptions import UnwrapFailedError -class _HasSuccessAndFailureTypes(Protocol): - """This protocol enforces container to have a ``.success_type`` field.""" - - success_type: ClassVar[type] - - -def is_successful(container: _HasSuccessAndFailureTypes) -> bool: +def is_successful(container: Unwrappable) -> bool: """ Determins if a container was successful or not. @@ -33,7 +27,11 @@ def is_successful(container: _HasSuccessAndFailureTypes) -> bool: >>> assert not is_successful(IOFailure(1)) This function can work with containers - that have ``.success_type`` class field. + that are instance of :class:`returns.interfaces.unwrappable.Unwrappable`. """ - return isinstance(container, container.success_type) + try: + container.unwrap() + except UnwrapFailedError: + return False + return True diff --git a/returns/pointfree.py b/returns/pointfree.py deleted file mode 100644 index 2ec62b997..000000000 --- a/returns/pointfree.py +++ /dev/null @@ -1,36 +0,0 @@ -from returns._generated.pointfree.alt import _alt as alt -from returns._generated.pointfree.apply import _apply as apply -from returns._generated.pointfree.bind import _bind as bind -from returns._generated.pointfree.bind_async import _bind_async as bind_async -from returns._generated.pointfree.bind_async_future import ( - _bind_async_future as bind_async_future, -) -from returns._generated.pointfree.bind_async_future_result import ( - _bind_async_future_result as bind_async_future_result, -) -from returns._generated.pointfree.bind_awaitable import ( - _bind_awaitable as bind_awaitable, -) -from returns._generated.pointfree.bind_context import ( - _bind_context as bind_context, -) -from returns._generated.pointfree.bind_context_ioresult import ( - _bind_context_ioresult as bind_context_ioresult, -) -from returns._generated.pointfree.bind_context_result import ( - _bind_context_result as bind_context_result, -) -from returns._generated.pointfree.bind_future import _bind_future as bind_future -from returns._generated.pointfree.bind_future_result import ( - _bind_future_result as bind_future_result, -) -from returns._generated.pointfree.bind_io import _bind_io as bind_io -from returns._generated.pointfree.bind_ioresult import ( - _bind_ioresult as bind_ioresult, -) -from returns._generated.pointfree.bind_result import _bind_result as bind_result -from returns._generated.pointfree.fix import _fix as fix -from returns._generated.pointfree.map import _map as map_ -from returns._generated.pointfree.rescue import _rescue as rescue -from returns._generated.pointfree.unify import _unify as unify -from returns._generated.pointfree.value_or import _value_or as value_or diff --git a/returns/pointfree/__init__.py b/returns/pointfree/__init__.py new file mode 100644 index 000000000..862145eb1 --- /dev/null +++ b/returns/pointfree/__init__.py @@ -0,0 +1,5 @@ +from returns.pointfree.apply import apply as apply +from returns.pointfree.bind import bind as bind +from returns.pointfree.bind_result import bind_result as bind_result +from returns.pointfree.map import map_ as map_ +from returns.pointfree.rescue import rescue as rescue diff --git a/returns/pointfree/apply.py b/returns/pointfree/apply.py new file mode 100644 index 000000000..5a5cae58c --- /dev/null +++ b/returns/pointfree/apply.py @@ -0,0 +1,56 @@ +from typing import Callable, TypeVar + +from returns.interfaces.applicative import ApplicativeN +from returns.methods.apply import internal_apply +from returns.primitives.hkt import Kinded, KindN, kinded + +_FirstType = TypeVar('_FirstType') +_SecondType = TypeVar('_SecondType') +_ThirdType = TypeVar('_ThirdType') +_UpdatedType = TypeVar('_UpdatedType') + +_ApplicativeKind = TypeVar('_ApplicativeKind', bound=ApplicativeN) + + +def apply( + container: KindN[ + _ApplicativeKind, + Callable[[_FirstType], _UpdatedType], + _SecondType, + _ThirdType, + ], +) -> Kinded[Callable[ + [KindN[_ApplicativeKind, _FirstType, _SecondType, _ThirdType]], + KindN[_ApplicativeKind, _UpdatedType, _SecondType, _ThirdType], +]]: + """ + Turns container containing a function into a callable. + + In other words, it modifies the function + signature from: ``Container[a -> b]`` to: ``Container[a] -> Container[b]`` + + This is how it should be used: + + .. code:: python + + >>> from returns.pointfree import apply + >>> from returns.maybe import Some, Nothing + + >>> def example(argument: int) -> int: + ... return argument + 1 + + >>> assert apply(Some(example))(Some(1)) == Some(2) + >>> assert apply(Some(example))(Nothing) == Nothing + >>> assert apply(Nothing)(Some(1)) == Nothing + >>> assert apply(Nothing)(Nothing) == Nothing + + Note, that this function works for all containers with ``.apply`` method. + See :class:`returns.interfaces.applicative.ApplicativeN` for more info. + + """ + @kinded + def factory( + other: KindN[_ApplicativeKind, _FirstType, _SecondType, _ThirdType], + ) -> KindN[_ApplicativeKind, _UpdatedType, _SecondType, _ThirdType]: + return internal_apply(other, container) + return factory diff --git a/returns/pointfree/bind.py b/returns/pointfree/bind.py new file mode 100644 index 000000000..7be78dba7 --- /dev/null +++ b/returns/pointfree/bind.py @@ -0,0 +1,55 @@ +from typing import Callable, TypeVar + +from returns.interfaces.bindable import BindableN +from returns.methods.bind import internal_bind +from returns.primitives.hkt import Kinded, KindN, kinded + +_FirstType = TypeVar('_FirstType') +_SecondType = TypeVar('_SecondType') +_ThirdType = TypeVar('_ThirdType') +_UpdatedType = TypeVar('_UpdatedType') + +_BindableKind = TypeVar('_BindableKind', bound=BindableN) + + +def bind( + function: Callable[ + [_FirstType], + KindN[_BindableKind, _UpdatedType, _SecondType, _ThirdType], + ], +) -> Kinded[Callable[ + [KindN[_BindableKind, _FirstType, _SecondType, _ThirdType]], + KindN[_BindableKind, _UpdatedType, _SecondType, _ThirdType], +]]: + """ + Turns function's input parameter from a regular value to a container. + + In other words, it modifies the function + signature from: ``a -> Container[b]`` + to: ``Container[a] -> Container[b]`` + + Similar to :func:`returns.pointfree.rescue`, + but works for successful containers. + This is how it should be used: + + .. code:: python + + >>> from returns.pointfree import bind + >>> from returns.maybe import Maybe, Some, Nothing + + >>> def example(argument: int) -> Maybe[int]: + ... return Some(argument + 1) + + >>> assert bind(example)(Some(1)) == Some(2) + >>> assert bind(example)(Nothing) == Nothing + + Note, that this function works for all containers with ``.bind`` method. + See :class:`returns.primitives.interfaces.bindable.BindableN` for more info. + + """ + @kinded + def factory( + container: KindN[_BindableKind, _FirstType, _SecondType, _ThirdType], + ) -> KindN[_BindableKind, _UpdatedType, _SecondType, _ThirdType]: + return internal_bind(container, function) + return factory diff --git a/returns/pointfree/bind_result.py b/returns/pointfree/bind_result.py new file mode 100644 index 000000000..3cf0d8c61 --- /dev/null +++ b/returns/pointfree/bind_result.py @@ -0,0 +1,51 @@ +from typing import TYPE_CHECKING, Callable, TypeVar + +from returns.interfaces.specific.result import ResultBasedN +from returns.methods.bind_result import internal_bind_result +from returns.primitives.hkt import Kinded, KindN, kinded + +if TYPE_CHECKING: + from returns.result import Result # noqa: WPS433 + +_FirstType = TypeVar('_FirstType', contravariant=True) +_SecondType = TypeVar('_SecondType') +_ThirdType = TypeVar('_ThirdType', contravariant=True) +_UpdatedType = TypeVar('_UpdatedType', covariant=True) + +_ResultBasedKind = TypeVar('_ResultBasedKind', bound=ResultBasedN) + + +def bind_result( + function: Callable[[_FirstType], 'Result[_UpdatedType, _SecondType]'], +) -> Kinded[Callable[ + [KindN[_ResultBasedKind, _FirstType, _SecondType, _ThirdType]], + KindN[_ResultBasedKind, _UpdatedType, _SecondType, _ThirdType], +]]: + """ + Composes successful container with a function that returns a container. + + In other words, it modifies the function's + signature from: ``a -> Result[b, c]`` + to: ``Container[a, c] -> Container[b, c]`` + + .. code:: python + + >>> from returns.io import IOSuccess + >>> from returns.context import RequiresContextResult + >>> from returns.result import Result, Success + >>> from returns.pointfree import bind_result + + >>> def returns_result(arg: int) -> Result[int, str]: + ... return Success(arg + 1) + + >>> bound = bind_result(returns_result) + >>> assert bound(IOSuccess(1)) == IOSuccess(2) + >>> assert bound(RequiresContextResult.from_value(1))(...) == Success(2) + + """ + @kinded + def factory( + container: KindN[_ResultBasedKind, _FirstType, _SecondType, _ThirdType], + ) -> KindN[_ResultBasedKind, _UpdatedType, _SecondType, _ThirdType]: + return internal_bind_result(container, function) + return factory diff --git a/returns/pointfree/map.py b/returns/pointfree/map.py new file mode 100644 index 000000000..87acd642b --- /dev/null +++ b/returns/pointfree/map.py @@ -0,0 +1,56 @@ +from typing import Callable, TypeVar + +from returns.interfaces.mappable import MappableN +from returns.methods.map import internal_map +from returns.primitives.hkt import Kinded, KindN, kinded + +_FirstType = TypeVar('_FirstType') +_SecondType = TypeVar('_SecondType') +_ThirdType = TypeVar('_ThirdType') +_UpdatedType = TypeVar('_UpdatedType') + +_MappableKind = TypeVar('_MappableKind', bound=MappableN) + + +def map_( + function: Callable[[_FirstType], _UpdatedType], +) -> Kinded[Callable[ + [KindN[_MappableKind, _FirstType, _SecondType, _ThirdType]], + KindN[_MappableKind, _UpdatedType, _SecondType, _ThirdType], +]]: + """ + Lifts function to be wrapped in a container for better composition. + + In other words, it modifies the function's + signature from: ``a -> b`` to: ``Container[a] -> Container[b]`` + + This is how it should be used: + + .. code:: python + + >>> import anyio + >>> from returns.future import Future + >>> from returns.io import IO + >>> from returns.pointfree import map_ + + >>> def example(argument: int) -> float: + ... return argument / 2 + + >>> async def main() -> Future[float]: + ... return await map_(example)(Future.from_value(1)) + + >>> assert anyio.run(main) == IO(0.5) + + Note, that this function works for all containers with ``.map`` method. + See :class:`returns.primitives.interfaces.mappable.MappableN` for more info. + + See also: + - https://wiki.haskell.org/Lifting + + """ + @kinded + def factory( + container: KindN[_MappableKind, _FirstType, _SecondType, _ThirdType], + ) -> KindN[_MappableKind, _UpdatedType, _SecondType, _ThirdType]: + return internal_map(container, function) + return factory diff --git a/returns/pointfree/rescue.py b/returns/pointfree/rescue.py new file mode 100644 index 000000000..b501bda30 --- /dev/null +++ b/returns/pointfree/rescue.py @@ -0,0 +1,54 @@ +from typing import Callable, TypeVar + +from returns.interfaces.rescuable import RescuableN +from returns.methods.rescue import internal_rescue +from returns.primitives.hkt import Kinded, KindN, kinded + +_FirstType = TypeVar('_FirstType') +_SecondType = TypeVar('_SecondType') +_ThirdType = TypeVar('_ThirdType') +_UpdatedType = TypeVar('_UpdatedType') + +_RescuableKind = TypeVar('_RescuableKind', bound=RescuableN) + + +def rescue( + function: Callable[ + [_SecondType], + KindN[_RescuableKind, _FirstType, _UpdatedType, _ThirdType], + ], +) -> Kinded[Callable[ + [KindN[_RescuableKind, _FirstType, _SecondType, _ThirdType]], + KindN[_RescuableKind, _FirstType, _UpdatedType, _ThirdType], +]]: + """ + Turns function's input parameter from a regular value to a container. + + In other words, it modifies the function + signature from: ``a -> Container[b]`` to: ``Container[a] -> Container[b]`` + + Similar to :func:`returns.pointfree.bind`, but works for failed containers. + + This is how it should be used: + + .. code:: python + + >>> from returns.pointfree import rescue + >>> from returns.result import Success, Failure, Result + + >>> def example(argument: int) -> Result[str, int]: + ... return Success(argument + 1) + + >>> assert rescue(example)(Success('a')) == Success('a') + >>> assert rescue(example)(Failure(1)) == Success(2) + + Note, that this function works for all containers with ``.rescue`` method. + See :class:`returns.interfaces.rescuable.Rescuable` for more info. + + """ + @kinded + def factory( + container: KindN[_RescuableKind, _FirstType, _SecondType, _ThirdType], + ) -> KindN[_RescuableKind, _FirstType, _UpdatedType, _ThirdType]: + return internal_rescue(container, function) + return factory diff --git a/returns/primitives/container.py b/returns/primitives/container.py index cb2d54ce0..82c3e3eb0 100644 --- a/returns/primitives/container.py +++ b/returns/primitives/container.py @@ -1,13 +1,8 @@ from abc import ABCMeta -from typing import Any, TypeVar +from typing import Any from returns.primitives.types import Immutable -_ValueType = TypeVar('_ValueType', covariant=True) -_NewValueType = TypeVar('_NewValueType') -_ErrorType = TypeVar('_ErrorType', covariant=True) -_NewErrorType = TypeVar('_NewErrorType') - class BaseContainer(Immutable, metaclass=ABCMeta): """Utility class to provide all needed magic methods to the context.""" diff --git a/returns/primitives/exceptions.py b/returns/primitives/exceptions.py index f394423a8..bba12d1fe 100644 --- a/returns/primitives/exceptions.py +++ b/returns/primitives/exceptions.py @@ -1,13 +1,15 @@ from typing import TYPE_CHECKING if TYPE_CHECKING: - from returns.primitives.container import BaseContainer # noqa: WPS433 + from returns.interfaces.unwrappable import Unwrappable # noqa: WPS433 class UnwrapFailedError(Exception): """Raised when a container can not be unwrapped into a meaningful value.""" - def __init__(self, container: 'BaseContainer') -> None: + __slots__ = ('halted_container',) + + def __init__(self, container: 'Unwrappable') -> None: """ Saves halted container in the inner state. diff --git a/returns/primitives/hkt.py b/returns/primitives/hkt.py new file mode 100644 index 000000000..cbda1761a --- /dev/null +++ b/returns/primitives/hkt.py @@ -0,0 +1,289 @@ +from typing import Callable, Generic, NoReturn, Tuple, TypeVar + +from typing_extensions import Protocol + +from returns.functions import identity + +_InstanceType = TypeVar('_InstanceType', covariant=True) +_TypeArgType1 = TypeVar('_TypeArgType1', covariant=True) +_TypeArgType2 = TypeVar('_TypeArgType2', covariant=True) +_TypeArgType3 = TypeVar('_TypeArgType3', covariant=True) + +_FunctionDefType = TypeVar( + '_FunctionDefType', + bound=Callable[..., 'KindN'], + covariant=True, # This is a must! Otherwise it would not work. +) +_FunctionType = TypeVar( + '_FunctionType', + bound=Callable[..., 'KindN'], +) + +_UpdatedType = TypeVar('_UpdatedType') +_FirstKind = TypeVar('_FirstKind') +_SecondKind = TypeVar('_SecondKind') + +# Used fore debound: +_T1 = TypeVar('_T1') +_T2 = TypeVar('_T2') +_T3 = TypeVar('_T3') + + +class KindN( + Generic[_InstanceType, _TypeArgType1, _TypeArgType2, _TypeArgType3], +): + """ + Emulation support for Higher Kinded Types. + + Consider ``KindN`` to be an alias of ``Generic`` type. + But with some extra goodies. + + ``KindN`` is the top-most type for other ``Kind`` types + like ``Kind1``, ``Kind2``, ``Kind3``, etc. + + The only difference between them is how many type arguments they can hold. + ``Kind1`` can hold just two type arguments: ``Kind1[IO, int]`` + which is almost equals to ``IO[int]``. + ``Kind2`` can hold just two type arguments: ``Kind2[IOResult, int, str]`` + which is almost equals to ``IOResult[int, str]``. + And so on. + + The idea behind ``KindN`` is that one cannot write this code: + + .. code:: python + + from typing import TypeVar + + T = TypeVar('T') + V = TypeVar('V') + + def impossible(generic: T, value: V) -> T[V]: + return generic(value) + + But, with ``KindN`` this becomes possible in a form of ``Kind1[T, V]``. + + .. note:: + To make sure it works correctly, + your type has to be a subtype of ``KindN``. + + We use a custom ``mypy`` plugin to make sure types are correct. + Otherwise, it is currently impossible to properly type this. + + We use "emulated Higher Kinded Types" concept. + Read the whitepaper: https://bit.ly/2ABACx2 + + ``KindN`` does not exist in runtime. It is used just for typing. + There are (and must be) no instances of this type directly. + + Implementation details + ~~~~~~~~~~~~~~~~~~~~~~ + We didn't use ``ABCMeta`` to disallow its creation, + because we don't want to have + a possible metaclass conflict with other metaclasses. + Current API allows you to mix ``KindN`` anywhere. + + We allow ``_InstanceType`` of ``KindN`` + to be ``Instance`` type or ``TypeVarType`` with ``upper_bound``. + To work with ``Instance`` types use ``dekind``. + To work with ``TypeVarType`` types use ``debound``. + + See also: + - https://arrow-kt.io/docs/0.10/patterns/glossary/#higher-kinds + - https://github.com/gcanti/fp-ts/blob/master/docs/guides/HKT.md + - https://bow-swift.io/docs/fp-concepts/higher-kinded-types + + """ + + __slots__ = () + + +#: Type alias for kinds with one type argument. +Kind1 = KindN[_InstanceType, _TypeArgType1, NoReturn, NoReturn] + +#: Type alias for kinds with two type arguments. +Kind2 = KindN[_InstanceType, _TypeArgType1, _TypeArgType2, NoReturn] + +#: Type alias for kinds with three type arguments. +Kind3 = KindN[_InstanceType, _TypeArgType1, _TypeArgType2, _TypeArgType3] + + +def dekind( + kind: KindN[_InstanceType, _TypeArgType1, _TypeArgType2, _TypeArgType3], +) -> _InstanceType: + """ + Turns ``Kind1[IO, int]`` type into real ``IO[int]`` type. + + Should be used when you are left with accidential ``Kind`` instance + when you really want to have the real type. + + Works with type arguments of any length. + + We use a custom ``mypy`` plugin to make sure types are correct. + Otherwise, it is currently impossible to properly type this. + + In runtime it just returns the passed argument, nothing really happens: + + .. code:: python + + >>> from returns.io import IO + >>> from returns.primitives.hkt import Kind1 + + >>> container: Kind1[IO, int] = IO(1) + >>> assert dekind(container) is container + + However, please, do not use this function + unless you know exactly what you are doing and why do you need it. + """ + return kind # type: ignore + + +# Utils to define kinded functions +# ================================ + +# TODO: in the future we would be able to write a custom plugin +# with `transform_kind(T) -> T'` support. +# It would visit all the possible `KindN[]` types in any type and run `dekind` +# on them, so this will be how it works: +# in: => Callable[[KindN[IO[Any], int]], KindN[IO[Any], str]] +# out: => Callable[[IO[int]], IO[str]] +# This will allow to have better support for callable protocols and similar. +# Blocked by: https://github.com/python/mypy/issues/9001 +class Kinded(Protocol[_FunctionDefType]): # type: ignore + """ + Protocol that tracks kinded functions calls. + + We use a custom ``mypy`` plugin to make sure types are correct. + Otherwise, it is currently impossible to properly type this. + """ + + __call__: _FunctionDefType + + +def kinded(function: _FunctionType) -> Kinded[_FunctionType]: + """ + Decorator to be used when you want to dekind the function's return type. + + Does nothing in runtime, just returns its argument. + + We use a custom ``mypy`` plugin to make sure types are correct. + Otherwise, it is currently impossible to properly type this. + + Here's an example of how it should be used: + + .. code:: python + + >>> from typing import TypeVar + >>> from returns.primitives.hkt import KindN, kinded + >>> from returns.interfaces.bindable import BindableN + + >>> _Binds = TypeVar('_Binds', bound=BindableN) # just an example + >>> _Type1 = TypeVar('_Type1') + >>> _Type2 = TypeVar('_Type2') + >>> _Type3 = TypeVar('_Type3') + + >>> @kinded + ... def bindable_identity( + ... container: KindN[_Binds, _Type1, _Type2, _Type3], + ... ) -> KindN[_Binds, _Type1, _Type2, _Type3]: + ... return container # just do nothing + + As you can see, here we annotate our return type as + ``-> KindN[_Binds, _Type1, _Type2, _Type3]``, + it would be true without ``@kinded`` decorator. + + But, ``@kinded`` decorator dekinds the return type and infers + the real type behind it: + + .. code:: python + + >>> from returns.io import IO, IOResult + + >>> assert bindable_identity(IO(1)) == IO(1) + >>> # => Revealed type: 'IO[int]' + + >>> iores: IOResult[int, str] = IOResult.from_value(1) + >>> assert bindable_identity(iores) == iores + >>> # => Revealed type: 'IOResult[int, str]' + + The difference is very clear in ``methods`` modules, like: + + - Raw :func:`returns.methods.bind.internal_bind` + that returns ``KindN`` instance + - User-facing :func:`returns.methods.bind.bind` + that returns the container type + + You must use this decorator for your own kinded functions as well. + """ + return function # type: ignore + + +def debound( + instance: KindN[_FirstKind, _TypeArgType1, _TypeArgType2, _TypeArgType3], +) -> Tuple[ + _FirstKind, + Callable[ + [KindN[_SecondKind, _T1, _T2, _T3]], + KindN[_FirstKind, _T1, _T2, _T3], + ], +]: + """ + Helper function to simplify work with ``KindN`` inside the kinded context. + + Here's the problem: + + .. code:: python + + from typing import TypeVar + from returns.primitives.hkt import KindN, kinded + from returns.interfaces.mappable import MappableN + + _Maps = TypeVar('_Maps', bound=MappableN) + + @kinded + def map_int( + container: KindN[_Maps, _T1, _T2, _T3], + ) -> KindN[_Maps, int, _T2, _T3]: + return container.map(int) # won't work! + + In this example, ``container.map(int)`` will fail with the type error, + because ``KindN`` does not have ``.map`` method. + + But, ``_Maps`` type has! Because it is bound to ``MappableN`` typeclass. + It means, that we have to debound ``container`` + to ``MappableN`` instead of ``KindN```: + + .. code:: python + + from returns.primitives.hkt import debound + + @kinded + def map_int( + container: KindN[_Maps, _T1, _T2, _T3], + ) -> KindN[_Maps, int, _T2, _T3]: + new_instance, _ = debound(container) + reveal_type(new_instance) # It is correct now! + # => MappableN[_T1, _T2, _T3] + + # But this line won't work just yet: + return new_instance.map(int) + # Because it has type 'KindN[MappableN, int, _T2, _T3]' + # But, expected type: 'KindN[_Maps, int, _T2, _T3]' + + We now need to somehow turn our type back to the initial one. + This is where the second element of the tuple becomes useful: + + .. code:: python + + from returns.primitives.hkt import debound + + @kinded + def map_int( + container: KindN[_Maps, _T1, _T2, _T3], + ) -> KindN[_Maps, int, _T2, _T3]: + new_instance, rebound = debound(container) + return rebound(new_instance.map(int)) # Now it works! + # Turns the return type to: 'KindN[_Maps, int, _T2, _T3]' + + And this will work corretly both in runtime and typechecking. + """ + return instance, identity # type: ignore diff --git a/returns/primitives/interfaces.py b/returns/primitives/interfaces.py deleted file mode 100644 index 75e143dc2..000000000 --- a/returns/primitives/interfaces.py +++ /dev/null @@ -1,212 +0,0 @@ -from typing import Any, Callable, TypeVar, Union - -from typing_extensions import Protocol, runtime - -_ValueType = TypeVar('_ValueType', covariant=True) -_NewValueType = TypeVar('_NewValueType') -_ErrorType = TypeVar('_ErrorType', covariant=True) -_NewErrorType = TypeVar('_NewErrorType') - - -@runtime -class Bindable(Protocol[_ValueType]): - """ - Represents a "context" in which calculations can be executed. - - ``Bindable`` allows you to bind together - a series of calculations while maintaining - the context of that specific container. - """ - - def bind( - self, function: Callable[[_ValueType], 'Bindable[_NewValueType]'], - ) -> 'Bindable[_NewValueType]': - """ - Applies 'function' to the result of a previous calculation. - - And returns a new container. - Works for containers that represent success. - Is the opposite of :meth:`~Rescueable.rescue`. - """ - - -@runtime -class Unifiable(Protocol[_ValueType, _ErrorType]): - """ - Represents a "context" in which calculations can be executed. - - ``Unifiable`` allows you to bind together - a series of calculations while maintaining - the context of that specific container. - - As the name suggests is used to unify error types - while binding the value type. - """ - - def unify( - self, - function: Callable[ - [_ValueType], - 'Unifiable[_NewValueType, _NewErrorType]', - ], - ) -> 'Unifiable[_NewValueType, Union[_ErrorType, _NewErrorType]]': - """ - Applies 'function' to the result of a previous calculation. - - And returns a new container. - Works for containers that represent success. - Works the same way as :meth:`~Bindable.bind`, - but has different type semantics. - Is the opposite of :meth:`~Rescueable.rescue`. - """ - - -@runtime -class Mappable(Protocol[_ValueType]): - """ - Allows to chain wrapped values with regular functions. - - Behaves like a functor. - - See also: - https://en.wikipedia.org/wiki/Functor - - """ - - def map( # noqa: WPS125 - self, function: Callable[[_ValueType], _NewValueType], - ) -> 'Mappable[_NewValueType]': - """ - Applies 'function' to the contents of the functor. - - And returns a new functor value. - Is the opposite of :meth:`~Fixable.fix`. - - Has :func:`returns.pointfree.map` helper with the inverse semantic. - """ - - -@runtime -class Fixable(Protocol[_ValueType, _ErrorType]): - """Represents containers that can be fixed and rescued.""" - - def fix( - self, function: Callable[[_ErrorType], _NewValueType], - ) -> 'Fixable[_NewValueType, _ErrorType]': - """ - Applies 'function' to the error and transforms failure to success. - - And returns a new functor value. - Works for containers that represent failure. - Is the opposite of :meth:`~Mappable.map`. - """ - - -@runtime -class Rescueable(Protocol[_NewValueType, _ErrorType]): - """ - Represents a "context" in which calculations can be executed. - - ``Rescueable`` allows you to bind together - a series of calculations while maintaining - the context of that specific container. - """ - - def rescue( - self, - function: Callable[ - [_ErrorType], 'Rescueable[_NewValueType, _NewErrorType]', - ], - ) -> 'Rescueable[_NewValueType, _NewErrorType]': - """ - Applies 'function' to the result of a previous calculation. - - And returns a new container. - Works for containers that represent failure. - Is the opposite of :meth:`~Bindable.bind`. - """ - - -@runtime -class Unwrapable(Protocol[_ValueType, _ErrorType]): - """Represents containers that can unwrap and return its wrapped value.""" - - def value_or( - self, default_value: _NewValueType, - ) -> Union[_ValueType, _NewValueType]: - """Forces to unwrap value from container or return a default.""" - - def unwrap(self) -> _ValueType: - """ - Custom magic method to unwrap inner value from container. - - Should be redefined for ones that actually have values. - And for ones that raise an exception for no values. - - This method is the opposite of :meth:`~Unwrapable.failure`. - """ - - def failure(self) -> _ErrorType: - """ - Custom magic method to unwrap inner value from the failed container. - - This method is the opposite of :meth:`~Unwrapable.unwrap`. - """ - - -@runtime -class Altable(Protocol[_ValueType, _ErrorType]): - """Allows to unwrap failures.""" - - def alt( - self, - function: Callable[[_ErrorType], _NewErrorType], - ) -> 'Fixable[_ValueType, _NewErrorType]': - """ - Uses 'function' to transform one error to another. - - And returns a new functor value. - Works for containers that represent failure. - Is the opposite of :meth:`~Mappable.map`. - """ - - -@runtime -class Applicative(Protocol[_ValueType]): - """ - Allows to create unit containers from raw values. - - All containers should support this interface. - - See also: - https://en.wikipedia.org/wiki/Applicative_functor - http://learnyouahaskell.com/functors-applicative-functors-and-monoids - - """ - - @classmethod - def from_value( - cls, inner_value: _NewValueType, - ) -> 'Unitable[_NewValueType, Any]': - """This method is required to create new containers.""" - - def apply( - self, - container: 'Applicative[Callable[[_ValueType], _NewValueType]]', - ) -> 'Applicative[_NewValueType]': - """Calls a wrapped function in a container on this container.""" - - -@runtime -class Unitable(Applicative[_ValueType], Protocol[_ValueType, _ErrorType]): - """ - Allows to create unit values from success and failure. - - This is a heavily ``Result``-related class. - """ - - @classmethod - def from_failure( - cls, inner_value: _NewErrorType, - ) -> 'Unitable[Any, _NewErrorType]': - """This method is required to create values that represent failure.""" diff --git a/returns/result.py b/returns/result.py index f0351f3ef..60bde50e1 100644 --- a/returns/result.py +++ b/returns/result.py @@ -1,11 +1,10 @@ -from abc import ABCMeta +from abc import ABCMeta, abstractmethod from functools import wraps from inspect import FrameInfo from typing import ( Any, Callable, ClassVar, - Generic, Iterable, List, NoReturn, @@ -19,8 +18,16 @@ from typing_extensions import final from returns._generated.iterable import iterable +from returns.interfaces import ( + applicative, + bindable, + mappable, + rescuable, + unwrappable, +) from returns.primitives.container import BaseContainer from returns.primitives.exceptions import UnwrapFailedError +from returns.primitives.hkt import Kind2 # Definitions: _ValueType = TypeVar('_ValueType', covariant=True) @@ -35,7 +42,12 @@ class Result( BaseContainer, - Generic[_ValueType, _ErrorType], + Kind2['Result', _ValueType, _ErrorType], + mappable.Mappable2[_ValueType, _ErrorType], + bindable.Bindable2[_ValueType, _ErrorType], + applicative.Applicative2[_ValueType, _ErrorType], + unwrappable.Unwrappable[_ValueType, _ErrorType], + rescuable.Rescuable2[_ValueType, _ErrorType], metaclass=ABCMeta, ): """ @@ -66,6 +78,7 @@ def trace(self) -> Optional[List[FrameInfo]]: """Returns a list with stack trace when :func:`~Failure` was called.""" return self._trace + @abstractmethod # noqa: WPS125 def map( # noqa: WPS125 self, function: Callable[[_ValueType], _NewValueType], @@ -84,11 +97,15 @@ def map( # noqa: WPS125 >>> assert Failure('a').map(mappable) == Failure('a') """ - raise NotImplementedError + @abstractmethod def apply( self, - container: 'Result[Callable[[_ValueType], _NewValueType], _ErrorType]', + container: Kind2[ + 'Result', + Callable[[_ValueType], _NewValueType], + _ErrorType, + ], ) -> 'Result[_NewValueType, _ErrorType]': """ Calls a wrapped function in a container on this container. @@ -107,11 +124,14 @@ def apply( >>> assert isinstance(with_failure, Result.failure_type) """ - raise NotImplementedError + @abstractmethod def bind( self, - function: Callable[[_ValueType], 'Result[_NewValueType, _ErrorType]'], + function: Callable[ + [_ValueType], + Kind2['Result', _NewValueType, _ErrorType], + ], ) -> 'Result[_NewValueType, _ErrorType]': """ Composes successful container with a function that returns a container. @@ -130,12 +150,12 @@ def bind( >>> assert Failure('a').bind(bindable) == Failure('a') """ - raise NotImplementedError def unify( self, function: Callable[ - [_ValueType], 'Result[_NewValueType, _NewErrorType]', + [_ValueType], + 'Result[_NewValueType, _NewErrorType]', ], ) -> 'Result[_NewValueType, Union[_ErrorType, _NewErrorType]]': """ @@ -164,6 +184,7 @@ def unify( """ return self.bind(function) # type: ignore + @abstractmethod def fix( self, function: Callable[[_ErrorType], _NewValueType], @@ -182,8 +203,8 @@ def fix( >>> assert Failure('a').fix(fixable) == Success('ab') """ - raise NotImplementedError + @abstractmethod def alt( self, function: Callable[[_ErrorType], _NewErrorType], @@ -202,12 +223,12 @@ def alt( >>> assert Failure('a').alt(altable) == Failure('ab') """ - raise NotImplementedError + @abstractmethod def rescue( self, function: Callable[ - [_ErrorType], 'Result[_ValueType, _NewErrorType]', + [_ErrorType], Kind2['Result', _ValueType, _NewErrorType], ], ) -> 'Result[_ValueType, _NewErrorType]': """ @@ -227,8 +248,8 @@ def rescue( >>> assert Failure('aa').rescue(rescuable) == Success('aab') """ - raise NotImplementedError + @abstractmethod def value_or( self, default_value: _NewValueType, @@ -243,8 +264,8 @@ def value_or( >>> assert Failure(1).value_or(2) == 2 """ - raise NotImplementedError + @abstractmethod def unwrap(self) -> _ValueType: """ Get value or raise exception. @@ -260,8 +281,8 @@ def unwrap(self) -> _ValueType: returns.primitives.exceptions.UnwrapFailedError """ - raise NotImplementedError + @abstractmethod def failure(self) -> _ErrorType: """ Get failed value or raise exception. @@ -277,7 +298,6 @@ def failure(self) -> _ErrorType: returns.primitives.exceptions.UnwrapFailedError """ - raise NotImplementedError @classmethod def from_value( @@ -286,7 +306,6 @@ def from_value( """ One more value to create success unit values. - This is a part of :class:`returns.primitives.interfaces.Unitable`. It is useful as a united way to create a new value from any container. .. code:: python @@ -307,7 +326,6 @@ def from_failure( """ One more value to create failure unit values. - This is a part of :class:`returns.primitives.interfaces.Unitable`. It is useful as a united way to create a new value from any container. .. code:: python diff --git a/setup.cfg b/setup.cfg index a353beef5..76dba1374 100644 --- a/setup.cfg +++ b/setup.cfg @@ -32,6 +32,7 @@ ignore = WPS113, WPS202, WPS214, + WPS215, WPS235, WPS320, WPS436, @@ -45,7 +46,8 @@ ignore = per-file-ignores = # We allow reexport: - returns/pointfree.py: F401, WPS201 + returns/pointfree/__init__.py: F401, WPS201 + returns/methods/__init__.py: F401, WPS201 returns/pipeline.py: F401 returns/context/__init__.py: F401, WPS201 # Disable some quality checks for the most heavy parts: @@ -56,7 +58,7 @@ per-file-ignores = returns/future.py: WPS437 returns/_generated/futures/*.py: WPS204, WPS433, WPS437 # We allow a lot of durty hacks in our plugins: - returns/contrib/mypy/*.py: WPS201 + returns/contrib/mypy/*.py: S101, WPS201 returns/contrib/pytest/plugin.py: WPS430, WPS433, WPS437, WPS609 # There are multiple assert's in tests: tests/*.py: S101, WPS204, WPS218, WPS226, WPS432, WPS436 @@ -71,7 +73,6 @@ include_trailing_comma = true use_parentheses = true # See https://github.com/timothycrosley/isort#multi-line-output-modes multi_line_output = 3 -default_section = FIRSTPARTY line_length = 80 @@ -115,7 +116,6 @@ exclude_lines = # a more strict default pragma \# pragma: no cover\b - ^\s*raise NotImplementedError\b ^if TYPE_CHECKING: diff --git a/tests/test_context/test_requires_context/test_context.py b/tests/test_context/test_requires_context/test_context.py index 27a74c814..b1cd86168 100644 --- a/tests/test_context/test_requires_context/test_context.py +++ b/tests/test_context/test_requires_context/test_context.py @@ -2,24 +2,8 @@ import pytest -from returns.context import Context, RequiresContext +from returns.context import Context from returns.primitives.exceptions import ImmutableStateError -from returns.primitives.interfaces import Applicative, Bindable, Mappable - - -@pytest.mark.parametrize('container', [ - RequiresContext(lambda deps: deps), - RequiresContext.from_value(1), - Context.ask(), -]) -@pytest.mark.parametrize('protocol', [ - Bindable, - Mappable, - Applicative, -]) -def test_protocols(container, protocol): - """Ensures that RequiresContext has all the right protocols.""" - assert isinstance(container, protocol) def test_context_immutable(): diff --git a/tests/test_context/test_requires_context_ioresult/test_context_ioresult.py b/tests/test_context/test_requires_context_ioresult/test_context_ioresult.py index 34a813164..8b6acbc75 100644 --- a/tests/test_context/test_requires_context_ioresult/test_context_ioresult.py +++ b/tests/test_context/test_requires_context_ioresult/test_context_ioresult.py @@ -3,43 +3,7 @@ import pytest from returns.context import ContextIOResult, RequiresContextIOResult -from returns.io import IOFailure, IOSuccess from returns.primitives.exceptions import ImmutableStateError -from returns.primitives.interfaces import ( - Altable, - Bindable, - Fixable, - Mappable, - Rescueable, - Unitable, - Unwrapable, -) -from returns.result import Failure, Success - - -@pytest.mark.parametrize('container', [ - RequiresContextIOResult(lambda _: IOSuccess(1)), - RequiresContextIOResult(lambda _: IOFailure(1)), - RequiresContextIOResult.from_value(1), - RequiresContextIOResult.from_failure(1), - RequiresContextIOResult.from_result(Success(1)), - RequiresContextIOResult.from_result(Failure(1)), - RequiresContextIOResult.from_ioresult(IOSuccess(1)), - RequiresContextIOResult.from_ioresult(IOFailure(1)), - ContextIOResult.ask(), -]) -@pytest.mark.parametrize('protocol', [ - Bindable, - Mappable, - Rescueable, - Unwrapable, - Altable, - Fixable, - Unitable, -]) -def test_protocols(container, protocol): - """Ensures that RequiresContext has all the right protocols.""" - assert isinstance(container, protocol) def test_context_ioresult_immutable(): diff --git a/tests/test_context/test_requires_context_ioresult/test_requires_context_ioresult_bind.py b/tests/test_context/test_requires_context_ioresult/test_requires_context_ioresult_bind.py index fcbb726de..45b40dd99 100644 --- a/tests/test_context/test_requires_context_ioresult/test_requires_context_ioresult_bind.py +++ b/tests/test_context/test_requires_context_ioresult/test_requires_context_ioresult_bind.py @@ -7,13 +7,13 @@ def test_bind(): """Ensures that bind works.""" - def factory(inner_value: int) -> RCR[int, float, str]: + def factory(inner_value: int) -> RCR[float, str, int]: if inner_value > 0: return RCR(lambda deps: IOSuccess(inner_value / deps)) return RCR.from_failure(str(inner_value)) input_value = 5 - bound: RCR[int, int, str] = RCR.from_value(input_value) + bound: RCR[int, str, int] = RCR.from_value(input_value) assert bound.bind(factory)(2) == factory(input_value)(2) assert bound.bind(factory)(2) == IOSuccess(2.5) @@ -29,8 +29,8 @@ def factory(inner_value: int) -> Result[int, str]: return Success(inner_value + 1) return Failure('nope') - first: RCR[int, int, str] = RCR.from_value(1) - third: RCR[int, int, str] = RCR.from_failure('a') + first: RCR[int, str, int] = RCR.from_value(1) + third: RCR[int, str, int] = RCR.from_failure('a') assert first.bind_result(factory)(RCR.empty) == IOSuccess(2) assert RCR.from_value(0).bind_result( @@ -46,8 +46,8 @@ def factory(inner_value: int) -> IOResult[int, str]: return IOSuccess(inner_value + 1) return IOFailure('nope') - first: RCR[int, int, str] = RCR.from_value(1) - third: RCR[int, int, str] = RCR.from_failure('a') + first: RCR[int, str, int] = RCR.from_value(1) + third: RCR[int, str, int] = RCR.from_failure('a') assert first.bind_ioresult(factory)(RCR.empty) == IOSuccess(2) assert RCR.from_value(0).bind_ioresult( @@ -58,11 +58,11 @@ def factory(inner_value: int) -> IOResult[int, str]: def test_bind_regular_context(): """Ensures that regular ``RequiresContext`` can be bound.""" - def factory(inner_value: int) -> RequiresContext[int, float]: + def factory(inner_value: int) -> RequiresContext[float, int]: return RequiresContext(lambda deps: inner_value / deps) - first: RCR[int, int, str] = RCR.from_value(1) - third: RCR[int, int, str] = RCR.from_failure('a') + first: RCR[int, str, int] = RCR.from_value(1) + third: RCR[int, str, int] = RCR.from_failure('a') assert first.bind_context(factory)(2) == IOSuccess(0.5) assert RCR.from_value(2).bind_context( @@ -73,11 +73,11 @@ def factory(inner_value: int) -> RequiresContext[int, float]: def test_bind_result_context(): """Ensures that ``RequiresContextResult`` can be bound.""" - def factory(inner_value: int) -> RequiresContextResult[int, float, str]: + def factory(inner_value: int) -> RequiresContextResult[float, str, int]: return RequiresContextResult(lambda deps: Success(inner_value / deps)) - first: RCR[int, int, str] = RCR.from_value(1) - third: RCR[int, int, str] = RCR.from_failure('a') + first: RCR[int, str, int] = RCR.from_value(1) + third: RCR[int, str, int] = RCR.from_failure('a') assert first.bind_context_result(factory)(2) == IOSuccess(0.5) assert RCR.from_value(2).bind_context_result( @@ -88,7 +88,7 @@ def factory(inner_value: int) -> RequiresContextResult[int, float, str]: def test_rescue_success(): """Ensures that rescue works for Success container.""" - def factory(inner_value) -> RCR[int, int, str]: + def factory(inner_value) -> RCR[int, str, int]: return RCR.from_value(inner_value * 2) assert RCR.from_value(5).rescue( @@ -101,7 +101,7 @@ def factory(inner_value) -> RCR[int, int, str]: def test_rescue_failure(): """Ensures that rescue works for Failure container.""" - def factory(inner_value) -> RCR[int, int, str]: + def factory(inner_value) -> RCR[int, str, int]: return RCR.from_failure(inner_value * 2) assert RCR.from_value(5).rescue( diff --git a/tests/test_context/test_requires_context_ioresult/test_requires_context_ioresult_cast.py b/tests/test_context/test_requires_context_ioresult/test_requires_context_ioresult_cast.py index 775ddee37..4db603f84 100644 --- a/tests/test_context/test_requires_context_ioresult/test_requires_context_ioresult_cast.py +++ b/tests/test_context/test_requires_context_ioresult/test_requires_context_ioresult_cast.py @@ -6,7 +6,7 @@ ) -def _function(arg: int) -> RequiresContextIOResultE[int, float]: +def _function(arg: int) -> RequiresContextIOResultE[float, int]: if arg == 0: return RequiresContextIOResult.from_failure( ZeroDivisionError('Divided by 0'), @@ -16,18 +16,18 @@ def _function(arg: int) -> RequiresContextIOResultE[int, float]: def test_requires_context_ioresulte(): """Ensures that RequiresContextIOResultE correctly typecast.""" - container: RequiresContextIOResult[int, float, Exception] = _function(1) + container: RequiresContextIOResult[float, Exception, int] = _function(1) assert container(0) == RequiresContextIOResult.from_value(10.0)(0) def test_requires_context_io_aliases(): """Ensures that ReaderIOResult correctly typecast.""" - container: ReaderIOResultE[int, float] = _function(1) - container2: ReaderIOResult[int, float, Exception] = _function(1) - container3: ReaderIOResultE[int, float] = ReaderIOResultE.from_value( + container: ReaderIOResultE[float, int] = _function(1) + container2: ReaderIOResult[float, Exception, int] = _function(1) + container3: ReaderIOResultE[float, int] = ReaderIOResultE.from_value( 10.0, ) - container4: ReaderIOResultE[int, float] = ReaderIOResult.from_value(10.0) + container4: ReaderIOResultE[float, int] = ReaderIOResult.from_value(10.0) assert container(0) == container2(0) == container3(0) == container4(0) assert container(0) == RequiresContextIOResult.from_value(10.0)(0) diff --git a/tests/test_context/test_requires_context_result/test_context_result.py b/tests/test_context/test_requires_context_result/test_context_result.py index d08b46ac5..413038493 100644 --- a/tests/test_context/test_requires_context_result/test_context_result.py +++ b/tests/test_context/test_requires_context_result/test_context_result.py @@ -4,39 +4,6 @@ from returns.context import ContextResult, RequiresContextResult from returns.primitives.exceptions import ImmutableStateError -from returns.primitives.interfaces import ( - Altable, - Bindable, - Fixable, - Mappable, - Rescueable, - Unitable, - Unwrapable, -) -from returns.result import Failure, Success - - -@pytest.mark.parametrize('container', [ - RequiresContextResult(lambda _: Success(1)), - RequiresContextResult(lambda _: Failure(1)), - RequiresContextResult.from_value(1), - RequiresContextResult.from_failure(1), - RequiresContextResult.from_result(Success(1)), - RequiresContextResult.from_result(Failure(1)), - ContextResult.ask(), -]) -@pytest.mark.parametrize('protocol', [ - Bindable, - Mappable, - Rescueable, - Unwrapable, - Altable, - Fixable, - Unitable, -]) -def test_protocols(container, protocol): - """Ensures that RequiresContext has all the right protocols.""" - assert isinstance(container, protocol) def test_context_result_immutable(): diff --git a/tests/test_context/test_requires_context_result/test_requires_context_result_bind.py b/tests/test_context/test_requires_context_result/test_requires_context_result_bind.py index c7ac486ce..626f54027 100644 --- a/tests/test_context/test_requires_context_result/test_requires_context_result_bind.py +++ b/tests/test_context/test_requires_context_result/test_requires_context_result_bind.py @@ -5,13 +5,13 @@ def test_bind(): """Ensures that bind works.""" - def factory(inner_value: int) -> RCR[int, float, str]: + def factory(inner_value: int) -> RCR[float, str, int]: if inner_value > 0: return RCR(lambda deps: Success(inner_value / deps)) return RCR.from_failure(str(inner_value)) input_value = 5 - bound: RCR[int, int, str] = RCR.from_value(input_value) + bound: RCR[int, str, int] = RCR.from_value(input_value) assert bound.bind(factory)(2) == factory(input_value)(2) assert bound.bind(factory)(2) == Success(2.5) @@ -27,8 +27,8 @@ def factory(inner_value: int) -> Result[int, str]: return Success(inner_value + 1) return Failure('nope') - first: RCR[int, int, str] = RCR.from_value(1) - third: RCR[int, int, str] = RCR.from_failure('a') + first: RCR[int, str, int] = RCR.from_value(1) + third: RCR[int, str, int] = RCR.from_failure('a') assert first.bind_result(factory)(RCR.empty) == Success(2) assert RCR.from_value(0).bind_result( @@ -39,11 +39,11 @@ def factory(inner_value: int) -> Result[int, str]: def test_bind_regular_context(): """Ensures that regular ``RequiresContext`` can be bound.""" - def factory(inner_value: int) -> RequiresContext[int, float]: + def factory(inner_value: int) -> RequiresContext[float, int]: return RequiresContext(lambda deps: inner_value / deps) - first: RCR[int, int, str] = RCR.from_value(1) - third: RCR[int, int, str] = RCR.from_failure('a') + first: RCR[int, str, int] = RCR.from_value(1) + third: RCR[int, str, int] = RCR.from_failure('a') assert first.bind_context(factory)(2) == Success(0.5) assert RCR.from_value(2).bind_context( @@ -54,7 +54,7 @@ def factory(inner_value: int) -> RequiresContext[int, float]: def test_rescue_success(): """Ensures that rescue works for Success container.""" - def factory(inner_value) -> RCR[int, int, str]: + def factory(inner_value) -> RCR[int, str, int]: return RCR.from_value(inner_value * 2) assert RCR.from_value(5).rescue( @@ -67,7 +67,7 @@ def factory(inner_value) -> RCR[int, int, str]: def test_rescue_failure(): """Ensures that rescue works for Failure container.""" - def factory(inner_value) -> RCR[int, int, str]: + def factory(inner_value) -> RCR[int, str, int]: return RCR.from_failure(inner_value * 2) assert RCR.from_value(5).rescue( diff --git a/tests/test_context/test_requires_context_result/test_requires_context_result_cast.py b/tests/test_context/test_requires_context_result/test_requires_context_result_cast.py index ed6fc6ba2..0e0403279 100644 --- a/tests/test_context/test_requires_context_result/test_requires_context_result_cast.py +++ b/tests/test_context/test_requires_context_result/test_requires_context_result_cast.py @@ -6,7 +6,7 @@ ) -def _function(arg: int) -> RequiresContextResultE[int, float]: +def _function(arg: int) -> RequiresContextResultE[float, int]: if arg == 0: return RequiresContextResult.from_failure( ZeroDivisionError('Divided by 0'), @@ -16,18 +16,18 @@ def _function(arg: int) -> RequiresContextResultE[int, float]: def test_requires_context_resulte(): """Ensures that RequiresContextResultE correctly typecast.""" - container: RequiresContextResult[int, float, Exception] = _function(1) + container: RequiresContextResult[float, Exception, int] = _function(1) assert container(0) == RequiresContextResult.from_value(10.0)(0) def test_requires_context_aliases(): """Ensures that ReaderResult correctly typecast.""" - container: ReaderResultE[int, float] = _function(1) - container2: ReaderResult[int, float, Exception] = _function(1) - container3: ReaderResultE[int, float] = ReaderResultE.from_value( + container: ReaderResultE[float, int] = _function(1) + container2: ReaderResult[float, Exception, int] = _function(1) + container3: ReaderResultE[float, int] = ReaderResultE.from_value( 10.0, ) - container4: ReaderResultE[int, float] = ReaderResult.from_value(10.0) + container4: ReaderResultE[float, int] = ReaderResult.from_value(10.0) assert container(0) == container2(0) == container3(0) == container4(0) assert container(0) == RequiresContextResult.from_value(10.0)(0) diff --git a/tests/test_future/test_future_container/test_future_container.py b/tests/test_future/test_future_container/test_future_container.py deleted file mode 100644 index 2e0bb1c56..000000000 --- a/tests/test_future/test_future_container/test_future_container.py +++ /dev/null @@ -1,17 +0,0 @@ -import pytest - -from returns.future import Future -from returns.primitives.interfaces import Applicative, Bindable, Mappable - - -@pytest.mark.parametrize('container', [ - Future.from_value(''), -]) -@pytest.mark.parametrize('protocol', [ - Bindable, - Mappable, - Applicative, -]) -def test_protocols(container, protocol): - """Ensures that Future has all the right protocols.""" - assert isinstance(container, protocol) diff --git a/tests/test_future/test_future_result/test_future_result_container.py b/tests/test_future/test_future_result/test_future_result_container.py deleted file mode 100644 index 7a336b35b..000000000 --- a/tests/test_future/test_future_result/test_future_result_container.py +++ /dev/null @@ -1,32 +0,0 @@ -import pytest - -from returns.future import FutureResult -from returns.primitives.interfaces import ( - Altable, - Bindable, - Fixable, - Mappable, - Rescueable, - Unifiable, - Unitable, - Unwrapable, -) - - -@pytest.mark.parametrize('container', [ - FutureResult.from_value(1), - FutureResult.from_failure(1), -]) -@pytest.mark.parametrize('protocol', [ - Bindable, - Mappable, - Rescueable, - Altable, - Fixable, - Unwrapable, - Unifiable, - Unitable, -]) -def test_protocols(container, protocol): - """Ensures that Future has all the right protocols.""" - assert isinstance(container, protocol) diff --git a/tests/test_io/test_io_container/test_io.py b/tests/test_io/test_io_container/test_io.py index dd2f85fe1..e6aa9c1a5 100644 --- a/tests/test_io/test_io_container/test_io.py +++ b/tests/test_io/test_io_container/test_io.py @@ -1,20 +1,6 @@ import pytest from returns.io import IO, IOFailure, IOResult, IOSuccess -from returns.primitives.interfaces import Applicative, Bindable, Mappable - - -@pytest.mark.parametrize('container', [ - IO(''), -]) -@pytest.mark.parametrize('protocol', [ - Bindable, - Mappable, - Applicative, -]) -def test_protocols(container, protocol): - """Ensures that IO has all the right protocols.""" - assert isinstance(container, protocol) def test_io_map(): diff --git a/tests/test_io/test_ioresult_container/test_ioresult.py b/tests/test_io/test_ioresult_container/test_ioresult.py deleted file mode 100644 index dcd3c4731..000000000 --- a/tests/test_io/test_ioresult_container/test_ioresult.py +++ /dev/null @@ -1,32 +0,0 @@ -import pytest - -from returns.io import IOFailure, IOSuccess -from returns.primitives.interfaces import ( - Altable, - Bindable, - Fixable, - Mappable, - Rescueable, - Unifiable, - Unitable, - Unwrapable, -) - - -@pytest.mark.parametrize('container', [ - IOSuccess(1), - IOFailure(1), -]) -@pytest.mark.parametrize('protocol', [ - Bindable, - Mappable, - Rescueable, - Unwrapable, - Altable, - Fixable, - Unitable, - Unifiable, -]) -def test_protocols(container, protocol): - """Ensures that RequiresContext has all the right protocols.""" - assert isinstance(container, protocol) diff --git a/tests/test_io/test_ioresult_container/test_ioresult_base.py b/tests/test_io/test_ioresult_container/test_ioresult_base.py index 253130496..3a38a6982 100644 --- a/tests/test_io/test_ioresult_container/test_ioresult_base.py +++ b/tests/test_io/test_ioresult_container/test_ioresult_base.py @@ -1,20 +1,6 @@ -import pytest - from returns.io import IOResult -@pytest.mark.parametrize('method_name', [ - 'bind', - 'bind_result', - 'rescue', -]) -def test_ioresult_abstract_method(method_name): - """Checks that Result itself contains abstract methods.""" - method = getattr(IOResult, method_name) - with pytest.raises(NotImplementedError): - method(object, lambda to_output: to_output) - - def test_ioresult_types(): """Ensures that Result has two types inside a class.""" assert isinstance(IOResult.success_type, type) diff --git a/tests/test_maybe/test_maybe_base.py b/tests/test_maybe/test_maybe_base.py index 109d287a1..e925a8c32 100644 --- a/tests/test_maybe/test_maybe_base.py +++ b/tests/test_maybe/test_maybe_base.py @@ -1,31 +1,6 @@ -import pytest - from returns.maybe import Maybe -@pytest.mark.parametrize('method_name', [ - 'bind', - 'map', - 'value_or', -]) -def test_maybe_abstract_method(method_name): - """Checks that Maybe itself contains abstract methods.""" - method = getattr(Maybe, method_name) - with pytest.raises(NotImplementedError): - method(object, lambda to_output: to_output) - - -@pytest.mark.parametrize('method_name', [ - 'unwrap', - 'failure', -]) -def test_maybe_abstract_method_single(method_name): - """Checks that Maybe itself contains abstract methods.""" - method = getattr(Maybe, method_name) - with pytest.raises(NotImplementedError): - method(object) - - def test_maybe_types(): """Checks that we have correct types inside Maybe.""" assert isinstance(Maybe.success_type, type) diff --git a/tests/test_maybe/test_maybe_equality.py b/tests/test_maybe/test_maybe_equality.py index 70a048bd1..98631a17c 100644 --- a/tests/test_maybe/test_maybe_equality.py +++ b/tests/test_maybe/test_maybe_equality.py @@ -4,27 +4,6 @@ from returns.maybe import Nothing, Some, _Nothing from returns.primitives.exceptions import ImmutableStateError -from returns.primitives.interfaces import ( - Applicative, - Bindable, - Mappable, - Unwrapable, -) - - -@pytest.mark.parametrize('container', [ - Nothing, - Some(1), -]) -@pytest.mark.parametrize('protocol', [ - Bindable, - Mappable, - Unwrapable, - Applicative, -]) -def test_protocols(container, protocol): - """Ensures that Maybe has all the right protocols.""" - assert isinstance(container, protocol) def test_equality(): diff --git a/tests/test_pipeline/test_managed/test_managed_reader_future_result.py b/tests/test_pipeline/test_managed/test_managed_reader_future_result.py index b0b6f0c84..676436ad4 100644 --- a/tests/test_pipeline/test_managed/test_managed_reader_future_result.py +++ b/tests/test_pipeline/test_managed/test_managed_reader_future_result.py @@ -8,19 +8,19 @@ from returns.result import Failure, Result, Success -def _acquire_success() -> ReaderFutureResult[NoDeps, str, str]: +def _acquire_success() -> ReaderFutureResult[str, str, NoDeps]: return ReaderFutureResult.from_value('acquire success') -def _acquire_failure() -> ReaderFutureResult[NoDeps, str, str]: +def _acquire_failure() -> ReaderFutureResult[str, str, NoDeps]: return ReaderFutureResult.from_failure('acquire failure') -def _use_success(inner_value: str) -> ReaderFutureResult[NoDeps, str, str]: +def _use_success(inner_value: str) -> ReaderFutureResult[str, str, NoDeps]: return ReaderFutureResult.from_value('use success') -def _use_failure(inner_value: str) -> ReaderFutureResult[NoDeps, str, str]: +def _use_failure(inner_value: str) -> ReaderFutureResult[str, str, NoDeps]: return ReaderFutureResult.from_failure('use failure') @@ -32,7 +32,7 @@ def __call__( self, inner_value: str, use_result: Result[str, str], - ) -> ReaderFutureResult[NoDeps, None, str]: + ) -> ReaderFutureResult[None, str, NoDeps]: self._logs.append((inner_value, use_result)) return ReaderFutureResult.from_value(None) @@ -45,7 +45,7 @@ def __call__( self, inner_value: str, use_result: Result[str, str], - ) -> ReaderFutureResult[NoDeps, None, str]: + ) -> ReaderFutureResult[None, str, NoDeps]: return ReaderFutureResult.from_failure('release failure') diff --git a/tests/test_pipeline/test_managed/test_managed_reader_ioresult.py b/tests/test_pipeline/test_managed/test_managed_reader_ioresult.py index e1959fca6..fcb5a9599 100644 --- a/tests/test_pipeline/test_managed/test_managed_reader_ioresult.py +++ b/tests/test_pipeline/test_managed/test_managed_reader_ioresult.py @@ -11,11 +11,11 @@ _acquire_failure = ReaderIOResult.from_failure('acquire failure') -def _use_success(inner_value: str) -> ReaderIOResult[NoDeps, str, str]: +def _use_success(inner_value: str) -> ReaderIOResult[str, str, NoDeps]: return ReaderIOResult.from_value('use success') -def _use_failure(inner_value: str) -> ReaderIOResult[NoDeps, str, str]: +def _use_failure(inner_value: str) -> ReaderIOResult[str, str, NoDeps]: return ReaderIOResult.from_failure('use failure') @@ -27,7 +27,7 @@ def __call__( self, inner_value: str, use_result: Result[str, str], - ) -> ReaderIOResult[NoDeps, None, str]: + ) -> ReaderIOResult[None, str, NoDeps]: self._logs.append((inner_value, use_result)) return ReaderIOResult.from_value(None) @@ -40,7 +40,7 @@ def __call__( self, inner_value: str, use_result: Result[str, str], - ) -> ReaderIOResult[NoDeps, None, str]: + ) -> ReaderIOResult[None, str, NoDeps]: return ReaderIOResult.from_failure('release failure') diff --git a/tests/test_pointfree/test_apply.py b/tests/test_pointfree/test_apply.py deleted file mode 100644 index 3225a0d18..000000000 --- a/tests/test_pointfree/test_apply.py +++ /dev/null @@ -1,89 +0,0 @@ -import pytest - -from returns.context import ( - RequiresContext, - RequiresContextIOResult, - RequiresContextResult, -) -from returns.future import Future, FutureResult -from returns.io import IO, IOFailure, IOResult, IOSuccess -from returns.maybe import Maybe, Nothing, Some -from returns.pointfree import apply -from returns.result import Failure, Result, Success - - -def _function(argument: int) -> str: - return str(argument + 1) - - -def test_apply_with_io(): - """Ensures that functions can be composed and return type is correct.""" - assert apply(IO(_function))(IO(1)) == IO('2') - - -def test_apply_with_ioresult(): - """Ensures that functions can be composed and return type is correct.""" - applied = apply(IOResult.from_value(_function)) - - assert applied(IOSuccess(1)) == IOSuccess('2') - assert applied(IOFailure('a')) == IOFailure('a') - - -def test_apply_with_maybe(): - """Ensures that functions can be composed and return type is correct.""" - applied = apply(Maybe.from_value(_function)) - - assert applied(Some(1)) == Some('2') - assert applied(Nothing) == Nothing - - -def test_apply_with_result(): - """Ensures that functions can be composed and return type is correct.""" - applied = apply(Result.from_value(_function)) - - assert applied(Success(1)) == Success('2') - assert applied(Failure('s')) == Failure('s') - - -def test_apply_with_context(): - """Ensures that functions can be composed and return type is correct.""" - applied = apply(RequiresContext.from_value(_function)) - - assert applied(RequiresContext.from_value(1))(...) == '2' - - -def test_apply_with_context_result(): - """Ensures that functions can be composed and return type is correct.""" - applied = apply(RequiresContextResult.from_value(_function)) - - assert applied( - RequiresContextResult.from_value(1), - )(...) == Success('2') - - -def test_apply_with_context_ioresult(): - """Ensures that functions can be composed and return type is correct.""" - applied = apply(RequiresContextIOResult.from_value(_function)) - - assert applied( - RequiresContextIOResult.from_value(1), - )(...) == IOSuccess('2') - - -@pytest.mark.anyio -async def test_apply_future(): - """Ensures that functions can be composed and return type is correct.""" - assert await apply( - Future.from_value(_function), - )(Future.from_value(1)) == IO('2') - - -@pytest.mark.anyio -async def test_apply_future_result(): - """Ensures that functions can be composed and return type is correct.""" - assert await apply( - FutureResult.from_value(_function), - )(FutureResult.from_value(1)) == IOSuccess('2') - assert await apply( - FutureResult.from_value(_function), - )(FutureResult.from_failure(1)) == IOFailure(1) diff --git a/tests/test_pointfree/test_bind_and_unify.py b/tests/test_pointfree/test_bind_and_unify.py deleted file mode 100644 index 7ed235c7e..000000000 --- a/tests/test_pointfree/test_bind_and_unify.py +++ /dev/null @@ -1,123 +0,0 @@ -import pytest - -from returns.context import ( - RequiresContext, - RequiresContextIOResult, - RequiresContextResult, -) -from returns.future import Future, FutureResult -from returns.io import IO, IOFailure, IOResult, IOSuccess -from returns.maybe import Maybe, Nothing, Some -from returns.pointfree import bind, unify -from returns.result import Failure, Result, Success - - -def _io_function(argument: int) -> IO[str]: - return IO(str(argument + 1)) - - -def _maybe_function(argument: int) -> Maybe[str]: - return Some(str(argument + 1)) - - -def _result_function(argument: int) -> Result[str, str]: - return Success(str(argument + 1)) - - -def _ioresult_function(argument: int) -> IOResult[str, str]: - return IOSuccess(str(argument + 1)) - - -def _context_function(argument: int) -> RequiresContext[int, int]: - return RequiresContext(lambda other: argument + other) - - -def _context_result_function( - argument: int, -) -> RequiresContextResult[int, int, str]: - return RequiresContextResult(lambda other: Success(argument + other)) - - -def _context_ioresult_function( - argument: int, -) -> RequiresContextIOResult[int, int, str]: - return RequiresContextIOResult(lambda other: IOSuccess(argument + other)) - - -def _future_function(argument: int) -> Future[str]: - return Future.from_value(str(argument + 1)) - - -def _future_result_function(argument: int) -> FutureResult[str, float]: - return FutureResult.from_value(str(argument + 1)) - - -def test_bind_with_io(): - """Ensures that functions can be composed and return type is correct.""" - bound = bind(_io_function) - - assert bound(IO(1)) == IO('2') - - -def test_bind_with_ioresult(): - """Ensures that functions can be composed and return type is correct.""" - bound = bind(_ioresult_function) - - assert bound(IOSuccess(1)) == IOSuccess('2') - assert bound(IOFailure('a')) == IOFailure('a') - assert bound(IOSuccess(1)) == unify(_ioresult_function)(IOSuccess(1)) - - -def test_bind_with_maybe(): - """Ensures that functions can be composed and return type is correct.""" - bound = bind(_maybe_function) - - assert bound(Some(1)) == Some('2') - assert bound(Nothing) == Nothing - - -def test_bind_with_result(): - """Ensures that functions can be composed and return type is correct.""" - bound = bind(_result_function) - - assert bound(Success(1)) == Success('2') - assert bound(Failure('s')) == Failure('s') - assert bound(Success(1)) == unify(_result_function)(Success(1)) - - -def test_bind_with_context(): - """Ensures that functions can be composed and return type is correct.""" - bound = bind(_context_function) - - assert bound(RequiresContext(lambda _: 3))(5) == 8 - - -def test_bind_with_context_result(): - """Ensures that functions can be composed and return type is correct.""" - bound = bind(_context_result_function) - - assert bound(RequiresContextResult.from_value(3))(5) == Success(8) - - -def test_bind_with_context_ioresult(): - """Ensures that functions can be composed and return type is correct.""" - bound = bind(_context_ioresult_function) - - assert bound(RequiresContextIOResult.from_value(3))(5) == IOSuccess(8) - - -@pytest.mark.anyio -async def test_bind_future(): - """Ensures that functions can be composed and return type is correct.""" - assert await bind(_future_function)(Future.from_value(1)) == IO('2') - - -@pytest.mark.anyio -async def test_bind_future_result(): - """Ensures that functions can be composed and return type is correct.""" - assert await bind(_future_result_function)( - FutureResult.from_value(1), - ) == IOSuccess('2') - assert await bind(_future_result_function)( - FutureResult.from_failure(1.0), - ) == IOFailure(1.0) diff --git a/tests/test_pointfree/test_rescue.py b/tests/test_pointfree/test_rescue.py deleted file mode 100644 index 3d49b3090..000000000 --- a/tests/test_pointfree/test_rescue.py +++ /dev/null @@ -1,80 +0,0 @@ -from returns.context import RequiresContextIOResult, RequiresContextResult -from returns.io import IOFailure, IOResult, IOSuccess -from returns.pointfree import rescue -from returns.result import Failure, Result, Success - - -def _result_function(argument: int) -> Result[int, str]: - if argument > 0: - return Success(argument + 1) - return Failure('nope') - - -def _ioresult_function(argument: int) -> IOResult[int, str]: - if argument > 0: - return IOSuccess(argument + 1) - return IOFailure('nope') - - -def _context_result_function( - argument: int, -) -> RequiresContextResult[int, int, str]: - if argument > 0: - return RequiresContextResult(lambda deps: Success(argument + deps)) - return RequiresContextResult.from_failure('nope') - - -def _context_ioresult_function( - argument: int, -) -> RequiresContextIOResult[int, int, str]: - if argument > 0: - return RequiresContextIOResult(lambda deps: IOSuccess(argument + deps)) - return RequiresContextIOResult.from_failure('nope') - - -def test_rescue_with_ioresult(): - """Ensures that functions can be composed and return type is correct.""" - rescued = rescue(_ioresult_function) - - assert rescued(IOSuccess(1)) == IOSuccess(1) - assert rescued(IOFailure(1)) == IOSuccess(2) - assert rescued(IOFailure(0)) == IOFailure('nope') - - -def test_rescue_with_result(): - """Ensures that functions can be composed and return type is correct.""" - rescued = rescue(_result_function) - - assert rescued(Success(1)) == Success(1) - assert rescued(Failure(1)) == Success(2) - assert rescued(Failure(0)) == Failure('nope') - - -def test_rescue_with_context_result(): - """Ensures that functions can be composed and return type is correct.""" - rescued = rescue(_context_result_function) - - assert rescued( - RequiresContextResult.from_value(1), - )(1) == Success(1) - assert rescued( - RequiresContextResult.from_failure(1), - )(1) == Success(2) - assert rescued( - RequiresContextResult.from_failure(0), - )(1) == Failure('nope') - - -def test_rescue_with_context_ioresult(): - """Ensures that functions can be composed and return type is correct.""" - rescued = rescue(_context_ioresult_function) - - assert rescued( - RequiresContextIOResult.from_value(1), - )(1) == IOSuccess(1) - assert rescued( - RequiresContextIOResult.from_failure(1), - )(1) == IOSuccess(2) - assert rescued( - RequiresContextIOResult.from_failure(0), - )(1) == IOFailure('nope') diff --git a/tests/test_result/test_result_base.py b/tests/test_result/test_result_base.py index 2dbdd8520..d39257507 100644 --- a/tests/test_result/test_result_base.py +++ b/tests/test_result/test_result_base.py @@ -1,34 +1,6 @@ -import pytest - from returns.result import Result -@pytest.mark.parametrize('method_name', [ - 'bind', - 'map', - 'rescue', - 'fix', - 'alt', - 'value_or', -]) -def test_result_abstract_method(method_name): - """Checks that Result itself contains abstract methods.""" - method = getattr(Result, method_name) - with pytest.raises(NotImplementedError): - method(object, lambda to_output: to_output) - - -@pytest.mark.parametrize('method_name', [ - 'failure', - 'unwrap', -]) -def test_result_abstract_method_single(method_name): - """Checks that Result itself contains abstract methods.""" - method = getattr(Result, method_name) - with pytest.raises(NotImplementedError): - method(object) - - def test_result_types(): """Ensures that Result has two types inside a class.""" assert isinstance(Result.success_type, type) diff --git a/tests/test_result/test_result_equality.py b/tests/test_result/test_result_equality.py index 84b0fd9db..b06ab48a0 100644 --- a/tests/test_result/test_result_equality.py +++ b/tests/test_result/test_result_equality.py @@ -3,38 +3,9 @@ import pytest from returns.primitives.exceptions import ImmutableStateError -from returns.primitives.interfaces import ( - Altable, - Bindable, - Fixable, - Mappable, - Rescueable, - Unifiable, - Unitable, - Unwrapable, -) from returns.result import Failure, Success -@pytest.mark.parametrize('container', [ - Failure(1), - Success(1), -]) -@pytest.mark.parametrize('protocol', [ - Bindable, - Mappable, - Fixable, - Rescueable, - Unwrapable, - Altable, - Unitable, - Unifiable, -]) -def test_protocols(container, protocol): - """Ensures that Result has all the right protocols.""" - assert isinstance(container, protocol) - - def test_nonequality(): """Ensures that containers are not compared to regular values.""" input_value = 5 diff --git a/typesafety/test_context/test_requires_context/test_context.yml b/typesafety/test_context/test_requires_context/test_context.yml index 597ee4f68..76db24558 100644 --- a/typesafety/test_context/test_requires_context/test_context.yml +++ b/typesafety/test_context/test_requires_context/test_context.yml @@ -19,4 +19,4 @@ main: | from returns.context import RequiresContext - reveal_type(RequiresContext.from_value(1)) # N: Revealed type is 'returns.context.requires_context.RequiresContext[Any, builtins.int*]' + reveal_type(RequiresContext.from_value(1)) # N: Revealed type is 'returns.context.requires_context.RequiresContext[builtins.int*, Any]' diff --git a/typesafety/test_context/test_requires_context/test_requires_context_cast.yml b/typesafety/test_context/test_requires_context/test_requires_context_cast.yml index 17853922d..3dec1a47a 100644 --- a/typesafety/test_context/test_requires_context/test_requires_context_cast.yml +++ b/typesafety/test_context/test_requires_context/test_requires_context_cast.yml @@ -3,10 +3,10 @@ main: | from returns.context import RequiresContext - first: RequiresContext[int, TypeError] # we can only return type - second: RequiresContext[int, Exception] = first + first: RequiresContext[TypeError, int] # we can only cast return type + second: RequiresContext[Exception, int] = first - reveal_type(second) # N: Revealed type is 'returns.context.requires_context.RequiresContext[builtins.int, builtins.Exception]' + reveal_type(second) # N: Revealed type is 'returns.context.requires_context.RequiresContext[builtins.Exception, builtins.int]' - case: context_wrong_cast @@ -14,7 +14,7 @@ main: | from returns.context import RequiresContext - first: RequiresContext[ValueError, TypeError] # we can only return type + first: RequiresContext[ValueError, TypeError] # we can only cast return type second: RequiresContext[Exception, Exception] = first out: | main:4: error: Incompatible types in assignment (expression has type "RequiresContext[ValueError, TypeError]", variable has type "RequiresContext[Exception, Exception]") @@ -34,18 +34,19 @@ class C(A): c = 3 - def func() -> RequiresContext[B, int]: + def func() -> RequiresContext[int, B]: return RequiresContext(lambda deps: deps.a + deps.b) - def second(a: int) -> RequiresContext[A, int]: + def second(a: int) -> RequiresContext[int, A]: return RequiresContext(lambda deps: deps.a + a) - def third(a: int) -> RequiresContext[C, int]: + def third(a: int) -> RequiresContext[int, C]: return RequiresContext(lambda deps: deps.c + a) reveal_type(func().bind(second)) reveal_type(func().bind(third)) out: | - main:21: note: Revealed type is 'returns.context.requires_context.RequiresContext[main.B, builtins.int*]' - main:22: error: Argument 1 to "bind" of "RequiresContext" has incompatible type "Callable[[int], RequiresContext[C, int]]"; expected "Callable[[int], RequiresContext[B, int]]" - main:22: note: Revealed type is 'returns.context.requires_context.RequiresContext[main.B, builtins.int*]' + main:21: error: Argument 1 to "bind" of "RequiresContext" has incompatible type "Callable[[int], RequiresContext[int, A]]"; expected "Callable[[int], KindN[RequiresContext[Any, Any], int, B, NoReturn]]" + main:21: note: Revealed type is 'returns.context.requires_context.RequiresContext[builtins.int*, main.B]' + main:22: error: Argument 1 to "bind" of "RequiresContext" has incompatible type "Callable[[int], RequiresContext[int, C]]"; expected "Callable[[int], KindN[RequiresContext[Any, Any], int, B, NoReturn]]" + main:22: note: Revealed type is 'returns.context.requires_context.RequiresContext[builtins.int*, main.B]' diff --git a/typesafety/test_context/test_requires_context/test_requires_context_type.yml b/typesafety/test_context/test_requires_context/test_requires_context_type.yml index 3b0a5650a..0d9419736 100644 --- a/typesafety/test_context/test_requires_context/test_requires_context_type.yml +++ b/typesafety/test_context/test_requires_context/test_requires_context_type.yml @@ -3,7 +3,7 @@ main: | from returns.context import RequiresContext - first: RequiresContext[int, str] + first: RequiresContext[str, int] reveal_type(first(1)) # N: Revealed type is 'builtins.str*' @@ -13,9 +13,9 @@ main: | from returns.context import RequiresContext - first: RequiresContext[int, str] + first: RequiresContext[str, int] - reveal_type(first.map(lambda char: float(char))) # N: Revealed type is 'returns.context.requires_context.RequiresContext[builtins.int, builtins.float*]' + reveal_type(first.map(lambda char: float(char))) # N: Revealed type is 'returns.context.requires_context.RequiresContext[builtins.float*, builtins.int]' - case: requires_context_apply_correct @@ -24,10 +24,10 @@ from typing import Callable from returns.context import RequiresContext - first: RequiresContext[int, str] - second: RequiresContext[int, Callable[[str], float]] + first: RequiresContext[str, int] + second: RequiresContext[Callable[[str], float], int] - reveal_type(first.apply(second)) # N: Revealed type is 'returns.context.requires_context.RequiresContext[builtins.int, builtins.float*]' + reveal_type(first.apply(second)) # N: Revealed type is 'returns.context.requires_context.RequiresContext[builtins.float*, builtins.int]' - case: requires_context_bind_correct @@ -35,12 +35,12 @@ main: | from returns.context import RequiresContext - first: RequiresContext[int, str] + first: RequiresContext[str, int] - def function(arg: str) -> RequiresContext[int, float]: + def function(arg: str) -> RequiresContext[float, int]: return RequiresContext.from_value(1.5) - reveal_type(first.bind(function)) # N: Revealed type is 'returns.context.requires_context.RequiresContext[builtins.int, builtins.float*]' + reveal_type(first.bind(function)) # N: Revealed type is 'returns.context.requires_context.RequiresContext[builtins.float*, builtins.int]' - case: requires_context_call_wrong @@ -48,7 +48,7 @@ main: | from returns.context import RequiresContext - first: RequiresContext[int, str] + first: RequiresContext[str, int] first('a') out: | main:4: error: Argument 1 to "__call__" of "RequiresContext" has incompatible type "str"; expected "int" @@ -59,7 +59,7 @@ main: | from returns.context import RequiresContext - first: RequiresContext[int, str] + first: RequiresContext[str, int] def function(arg: int) -> int: return arg + 1 @@ -74,14 +74,14 @@ main: | from returns.context import RequiresContext - first: RequiresContext[int, str] + first: RequiresContext[str, int] - def function(arg: float) -> RequiresContext[int, float]: + def function(arg: float) -> RequiresContext[float, int]: return RequiresContext.from_value(1.5) first.bind(function) out: | - main:8: error: Argument 1 to "bind" of "RequiresContext" has incompatible type "Callable[[float], RequiresContext[int, float]]"; expected "Callable[[str], RequiresContext[int, float]]" + main:8: error: Argument 1 to "bind" of "RequiresContext" has incompatible type "Callable[[float], RequiresContext[float, int]]"; expected "Callable[[str], KindN[RequiresContext[Any, Any], float, int, NoReturn]]" - case: requires_context_bind_wrong2 @@ -89,11 +89,11 @@ main: | from returns.context import RequiresContext - first: RequiresContext[int, str] + first: RequiresContext[str, int] - def function(arg: str) -> RequiresContext[str, float]: + def function(arg: str) -> RequiresContext[float, str]: return RequiresContext.from_value(1.5) first.bind(function) out: | - main:8: error: Argument 1 to "bind" of "RequiresContext" has incompatible type "Callable[[str], RequiresContext[str, float]]"; expected "Callable[[str], RequiresContext[int, float]]" + main:8: error: Argument 1 to "bind" of "RequiresContext" has incompatible type "Callable[[str], RequiresContext[float, str]]"; expected "Callable[[str], KindN[RequiresContext[Any, Any], float, int, NoReturn]]" diff --git a/typesafety/test_context/test_requires_context/test_requires_context_typecast.yml b/typesafety/test_context/test_requires_context/test_requires_context_typecast.yml index f228e492b..9ac498c44 100644 --- a/typesafety/test_context/test_requires_context/test_requires_context_typecast.yml +++ b/typesafety/test_context/test_requires_context/test_requires_context_typecast.yml @@ -4,9 +4,9 @@ from returns.context import RequiresContext from typing import Iterable - x: Iterable[RequiresContext[str, int]] + x: Iterable[RequiresContext[int, str]] - reveal_type(RequiresContext.from_iterable(x)) # N: Revealed type is 'returns.context.requires_context.RequiresContext[builtins.str*, typing.Sequence[builtins.int*]]' + reveal_type(RequiresContext.from_iterable(x)) # N: Revealed type is 'returns.context.requires_context.RequiresContext[typing.Sequence[builtins.str*], builtins.int*]' - case: requires_context_from_requires_context_ioresult @@ -15,9 +15,9 @@ from returns.context import RequiresContext from returns.context import RequiresContextIOResult - x: RequiresContextIOResult[str, int, float] + x: RequiresContextIOResult[int, float, str] - reveal_type(RequiresContext.from_requires_context_ioresult(x)) # N: Revealed type is 'returns.context.requires_context.RequiresContext[builtins.str*, returns.io.IOResult[builtins.int*, builtins.float*]]' + reveal_type(RequiresContext.from_requires_context_ioresult(x)) # N: Revealed type is 'returns.context.requires_context.RequiresContext[returns.io.IOResult[builtins.int*, builtins.float*], builtins.str*]' - case: requires_context_from_requires_context_result @@ -26,6 +26,17 @@ from returns.context import RequiresContext from returns.context import RequiresContextResult - x: RequiresContextResult[str, int, float] + x: RequiresContextResult[int, float, str] - reveal_type(RequiresContext.from_requires_context_result(x)) # N: Revealed type is 'returns.context.requires_context.RequiresContext[builtins.str*, returns.result.Result[builtins.int*, builtins.float*]]' + reveal_type(RequiresContext.from_requires_context_result(x)) # N: Revealed type is 'returns.context.requires_context.RequiresContext[returns.result.Result[builtins.int*, builtins.float*], builtins.str*]' + + +- case: requires_context_from_requires_context_future_result + disable_cache: true + main: | + from returns.context import RequiresContext + from returns.context import RequiresContextFutureResult + + x: RequiresContextFutureResult[int, float, str] + + reveal_type(RequiresContext.from_requires_context_future_result(x)) # N: Revealed type is 'returns.context.requires_context.RequiresContext[returns.future.FutureResult[builtins.int*, builtins.float*], builtins.str*]' diff --git a/typesafety/test_context/test_requires_context_future_result/test_context_future_result.yml b/typesafety/test_context/test_requires_context_future_result/test_context_future_result.yml index 98f0bde6f..4f7a6b8d7 100644 --- a/typesafety/test_context/test_requires_context_future_result/test_context_future_result.yml +++ b/typesafety/test_context/test_requires_context_future_result/test_context_future_result.yml @@ -3,7 +3,7 @@ main: | from returns.context import ContextFutureResult - reveal_type(ContextFutureResult.ask()) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[, , Any]' + reveal_type(ContextFutureResult.ask()) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[, Any, ]' - case: context_result_future_ask2 @@ -11,4 +11,4 @@ main: | from returns.context import ContextFutureResult - reveal_type(ContextFutureResult[str].ask()) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.str*, builtins.str*, Any]' + reveal_type(ContextFutureResult[str].ask()) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.str*, Any, builtins.str*]' diff --git a/typesafety/test_context/test_requires_context_future_result/test_requires_context_future_result.yml b/typesafety/test_context/test_requires_context_future_result/test_requires_context_future_result.yml index 3d99a69c7..95ef78b87 100644 --- a/typesafety/test_context/test_requires_context_future_result/test_requires_context_future_result.yml +++ b/typesafety/test_context/test_requires_context_future_result/test_requires_context_future_result.yml @@ -1,11 +1,21 @@ +- case: requires_context_future_result_call + disable_cache: true + main: | + from returns.context import RequiresContextFutureResult + + x: RequiresContextFutureResult[int, float, str] + + reveal_type(x('a')) # N: Revealed type is 'returns.future.FutureResult[builtins.int*, builtins.float*]' + + - case: requires_context_future_result_map disable_cache: true main: | from returns.context import RequiresContextFutureResult - x: RequiresContextFutureResult[str, int, float] + x: RequiresContextFutureResult[int, float, str] - reveal_type(x.map(bool)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.str, builtins.bool*, builtins.float]' + reveal_type(x.map(bool)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.float, builtins.str]' - case: requires_context_future_result_apply @@ -14,10 +24,10 @@ from typing import Callable from returns.context import RequiresContextFutureResult - x: RequiresContextFutureResult[str, int, float] - y: RequiresContextFutureResult[str, Callable[[int], bool], float] + x: RequiresContextFutureResult[int, float, str] + y: RequiresContextFutureResult[Callable[[int], bool], float, str] - reveal_type(x.apply(y)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.str, builtins.bool*, builtins.float]' + reveal_type(x.apply(y)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.float, builtins.str]' - case: requires_context_future_result_bind @@ -25,12 +35,12 @@ main: | from returns.context import RequiresContextFutureResult - x: RequiresContextFutureResult[str, int, float] + x: RequiresContextFutureResult[int, float, str] - def test(param: int) -> RequiresContextFutureResult[str, bool, float]: + def test(param: int) -> RequiresContextFutureResult[bool, float, str]: ... - reveal_type(x.bind(test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.str, builtins.bool*, builtins.float]' + reveal_type(x.bind(test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.float, builtins.str]' - case: requires_context_future_result_bind_awaitable @@ -41,9 +51,9 @@ async def bind_awaitable(arg: int) -> float: ... - first: RequiresContextFutureResult[bool, int, str] + first: RequiresContextFutureResult[int, str, bool] - reveal_type(first.bind_awaitable(bind_awaitable)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool, builtins.float*, builtins.str]' + reveal_type(first.bind_awaitable(bind_awaitable)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.float*, builtins.str, builtins.bool]' - case: requires_context_future_result_bind_async @@ -51,12 +61,12 @@ main: | from returns.context import RequiresContextFutureResult - async def bind_async(arg: int) -> RequiresContextFutureResult[bool, float, str]: + async def bind_async(arg: int) -> RequiresContextFutureResult[float, str, bool]: ... - first: RequiresContextFutureResult[bool, int, str] + first: RequiresContextFutureResult[int, str, bool] - reveal_type(first.bind_async(bind_async)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool, builtins.float*, builtins.str]' + reveal_type(first.bind_async(bind_async)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.float*, builtins.str, builtins.bool]' - case: requires_context_future_result_bind_result @@ -65,12 +75,12 @@ from returns.context import RequiresContextFutureResult from returns.result import Result - x: RequiresContextFutureResult[str, int, float] + x: RequiresContextFutureResult[int, float, str] def test(param: int) -> Result[bool, float]: ... - reveal_type(x.bind_result(test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.str, builtins.bool*, builtins.float]' + reveal_type(x.bind_result(test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.float, builtins.str]' - case: requires_context_futureresult_bind_ioresult @@ -79,12 +89,12 @@ from returns.context import RequiresContextFutureResult from returns.io import IOResult - x: RequiresContextFutureResult[str, int, float] + x: RequiresContextFutureResult[int, float, str] def test(param: int) -> IOResult[bool, float]: ... - reveal_type(x.bind_ioresult(test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.str, builtins.bool*, builtins.float]' + reveal_type(x.bind_ioresult(test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.float, builtins.str]' - case: requires_context_future_result_bind_io @@ -93,12 +103,12 @@ from returns.context import RequiresContextFutureResult from returns.io import IO - x: RequiresContextFutureResult[str, int, float] + x: RequiresContextFutureResult[int, float, str] def test(param: int) -> IO[bool]: ... - reveal_type(x.bind_io(test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.str, builtins.bool*, builtins.float]' + reveal_type(x.bind_io(test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.float, builtins.str]' - case: requires_context_futureresult_bind_future @@ -107,12 +117,12 @@ from returns.context import RequiresContextFutureResult from returns.future import Future - x: RequiresContextFutureResult[str, int, float] + x: RequiresContextFutureResult[int, float, str] def test(param: int) -> Future[bool]: ... - reveal_type(x.bind_future(test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.str, builtins.bool*, builtins.float]' + reveal_type(x.bind_future(test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.float, builtins.str]' - case: requires_context_futureresult_bind_future_result @@ -121,12 +131,12 @@ from returns.context import RequiresContextFutureResult from returns.future import FutureResult - x: RequiresContextFutureResult[str, int, float] + x: RequiresContextFutureResult[int, float, str] def test(param: int) -> FutureResult[bool, float]: ... - reveal_type(x.bind_future_result(test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.str, builtins.bool*, builtins.float]' + reveal_type(x.bind_future_result(test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.float, builtins.str]' - case: requires_context_futureresult_bind_async_future @@ -135,12 +145,12 @@ from returns.context import RequiresContextFutureResult from returns.future import Future - x: RequiresContextFutureResult[str, int, float] + x: RequiresContextFutureResult[int, float, str] async def test(param: int) -> Future[bool]: ... - reveal_type(x.bind_async_future(test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.str, builtins.bool*, builtins.float]' + reveal_type(x.bind_async_future(test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.float, builtins.str]' - case: requires_context_futureresult_bind_async_future_result @@ -149,12 +159,12 @@ from returns.context import RequiresContextFutureResult from returns.future import FutureResult - x: RequiresContextFutureResult[str, int, float] + x: RequiresContextFutureResult[int, float, str] async def test(param: int) -> FutureResult[bool, float]: ... - reveal_type(x.bind_async_future_result(test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.str, builtins.bool*, builtins.float]' + reveal_type(x.bind_async_future_result(test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.float, builtins.str]' - case: requires_context_future_result_bind_context @@ -162,12 +172,12 @@ main: | from returns.context import RequiresContextFutureResult, RequiresContext - x: RequiresContextFutureResult[str, int, float] + x: RequiresContextFutureResult[int, float, str] - def test(param: int) -> RequiresContext[str, bool]: + def test(param: int) -> RequiresContext[bool, str]: ... - reveal_type(x.bind_context(test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.str, builtins.bool*, builtins.float]' + reveal_type(x.bind_context(test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.float, builtins.str]' - case: requires_context_future_result_bind_context_result @@ -175,12 +185,12 @@ main: | from returns.context import RequiresContextFutureResult, RequiresContextResult - x: RequiresContextFutureResult[str, int, float] + x: RequiresContextFutureResult[int, float, str] - def test(param: int) -> RequiresContextResult[str, bool, float]: + def test(param: int) -> RequiresContextResult[bool, float, str]: ... - reveal_type(x.bind_context_result(test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.str, builtins.bool*, builtins.float]' + reveal_type(x.bind_context_result(test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.float, builtins.str]' - case: requires_context_future_result_bind_context_ioresult @@ -188,12 +198,12 @@ main: | from returns.context import RequiresContextFutureResult, RequiresContextIOResult - x: RequiresContextFutureResult[str, int, float] + x: RequiresContextFutureResult[int, float, str] - def test(param: int) -> RequiresContextIOResult[str, bool, float]: + def test(param: int) -> RequiresContextIOResult[bool, float, str]: ... - reveal_type(x.bind_context_ioresult(test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.str, builtins.bool*, builtins.float]' + reveal_type(x.bind_context_ioresult(test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.float, builtins.str]' - case: requires_context_future_result_rescue @@ -201,12 +211,12 @@ main: | from returns.context import RequiresContextFutureResult - x: RequiresContextFutureResult[str, int, float] + x: RequiresContextFutureResult[int, float, str] - def test(param: float) -> RequiresContextFutureResult[str, int, bool]: + def test(param: float) -> RequiresContextFutureResult[int, bool, str]: ... - reveal_type(x.rescue(test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.str, builtins.int, builtins.bool*]' + reveal_type(x.rescue(test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.int, builtins.bool*, builtins.str]' - case: requires_context_future_result_fix @@ -214,12 +224,12 @@ main: | from returns.context import RequiresContextFutureResult - x: RequiresContextFutureResult[str, int, float] + x: RequiresContextFutureResult[int, float, str] def test(param: float) -> bool: ... - reveal_type(x.fix(test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.str, builtins.bool*, builtins.float]' + reveal_type(x.fix(test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.float, builtins.str]' - case: requires_context_future_result_alt @@ -227,39 +237,9 @@ main: | from returns.context import RequiresContextFutureResult - x: RequiresContextFutureResult[str, int, float] + x: RequiresContextFutureResult[int, float, str] def test(param: float) -> bool: ... - reveal_type(x.alt(test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.str, builtins.int, builtins.bool*]' - - -- case: requires_context_future_result_value_or - disable_cache: true - main: | - from returns.context import RequiresContextFutureResult - - first: RequiresContextFutureResult[object, int, bool] - - reveal_type(first.value_or('a')) # N: Revealed type is 'def (builtins.object) -> typing.Awaitable[returns.io.IO[Union[builtins.int, builtins.str*]]]' - - -- case: requires_context_future_result_unwrap - disable_cache: true - main: | - from returns.context import RequiresContextFutureResult - - first: RequiresContextFutureResult[object, int, str] - - reveal_type(first.unwrap()) # N: Revealed type is 'def (builtins.object*) -> typing.Awaitable[returns.io.IO[builtins.int*]]' - - -- case: requires_context_future_result_failure - disable_cache: true - main: | - from returns.context import RequiresContextFutureResult - - first: RequiresContextFutureResult[object, int, str] - - reveal_type(first.failure()) # N: Revealed type is 'def (builtins.object*) -> typing.Awaitable[returns.io.IO[builtins.str*]]' + reveal_type(x.alt(test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.int, builtins.bool*, builtins.str]' diff --git a/typesafety/test_context/test_requires_context_future_result/test_requires_context_future_result_aliases.yml b/typesafety/test_context/test_requires_context_future_result/test_requires_context_future_result_aliases.yml index 4cba172ea..bd0fee72a 100644 --- a/typesafety/test_context/test_requires_context_future_result/test_requires_context_future_result_aliases.yml +++ b/typesafety/test_context/test_requires_context_future_result/test_requires_context_future_result_aliases.yml @@ -8,8 +8,8 @@ ReaderFutureResultE, ) - x: RequiresContextFutureResult[str, int, Exception] + x: RequiresContextFutureResult[int, Exception, str] - x1: RequiresContextFutureResultE[str, int] = x - x2: ReaderFutureResult[str, int, Exception] = x - x3: ReaderFutureResultE[str, int] = x + x1: RequiresContextFutureResultE[int, str] = x + x2: ReaderFutureResult[int, Exception, str] = x + x3: ReaderFutureResultE[int, str] = x diff --git a/typesafety/test_context/test_requires_context_future_result/test_requires_context_future_result_cast.yml b/typesafety/test_context/test_requires_context_future_result/test_requires_context_future_result_cast.yml index fae557e3d..3029f67a2 100644 --- a/typesafety/test_context/test_requires_context_future_result/test_requires_context_future_result_cast.yml +++ b/typesafety/test_context/test_requires_context_future_result/test_requires_context_future_result_cast.yml @@ -3,8 +3,8 @@ main: | from returns.context import RequiresContextFutureResult - first: RequiresContextFutureResult[str, object, Exception] = RequiresContextFutureResult.from_value(1) - reveal_type(first) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.str, builtins.object, builtins.Exception]' + first: RequiresContextFutureResult[object, Exception, str] = RequiresContextFutureResult.from_value(1) + reveal_type(first) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.object, builtins.Exception, builtins.str]' - case: requires_context_future_result_failure_cast @@ -12,8 +12,8 @@ main: | from returns.context import RequiresContextFutureResult - first: RequiresContextFutureResult[str, object, Exception] = RequiresContextFutureResult.from_failure(TypeError()) - reveal_type(first) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.str, builtins.object, builtins.Exception]' + first: RequiresContextFutureResult[object, Exception, str] = RequiresContextFutureResult.from_failure(TypeError()) + reveal_type(first) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.object, builtins.Exception, builtins.str]' - case: requires_context_future_result_env_cast @@ -21,7 +21,18 @@ main: | from returns.context import RequiresContextFutureResult - first: RequiresContextFutureResult[object, object, Exception] - second: RequiresContextFutureResult[str, object, Exception] = first + first: RequiresContextFutureResult[object, Exception, object] + second: RequiresContextFutureResult[object, Exception, str] = first - reveal_type(second) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.str, builtins.object, builtins.Exception]' + reveal_type(second) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.object, builtins.Exception, builtins.str]' + + +- case: requires_context_future_result_wrong_cast + disable_cache: true + main: | + from returns.context import RequiresContextFutureResult + + first: RequiresContextFutureResult[ValueError, TypeError, IndexError] + second: RequiresContextFutureResult[Exception, Exception, Exception] = first + out: | + main:4: error: Incompatible types in assignment (expression has type "RequiresContextFutureResult[ValueError, TypeError, IndexError]", variable has type "RequiresContextFutureResult[Exception, Exception, Exception]") diff --git a/typesafety/test_context/test_requires_context_future_result/test_requires_context_future_result_unit.yml b/typesafety/test_context/test_requires_context_future_result/test_requires_context_future_result_unit.yml index 296ab5776..f78600204 100644 --- a/typesafety/test_context/test_requires_context_future_result/test_requires_context_future_result_unit.yml +++ b/typesafety/test_context/test_requires_context_future_result/test_requires_context_future_result_unit.yml @@ -3,7 +3,7 @@ main: | from returns.context import RequiresContextFutureResult - reveal_type(RequiresContextFutureResult.from_value(1)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[Any, builtins.int*, Any]' + reveal_type(RequiresContextFutureResult.from_value(1)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.int*, Any, Any]' - case: requires_context_future_result_failure @@ -11,7 +11,7 @@ main: | from returns.context import RequiresContextFutureResult - reveal_type(RequiresContextFutureResult.from_failure(1)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[Any, Any, builtins.int*]' + reveal_type(RequiresContextFutureResult.from_failure(1)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[Any, builtins.int*, Any]' - case: requires_context_future_result_from_iterable @@ -20,9 +20,9 @@ from returns.context import RequiresContextFutureResult from typing import Iterable - x: Iterable[RequiresContextFutureResult[str, int, float]] + x: Iterable[RequiresContextFutureResult[int, float, str]] - reveal_type(RequiresContextFutureResult.from_iterable(x)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.str*, typing.Sequence[builtins.int*], builtins.float*]' + reveal_type(RequiresContextFutureResult.from_iterable(x)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[typing.Sequence[builtins.int*], builtins.float*, builtins.str*]' - case: requires_context_future_result_result @@ -33,7 +33,7 @@ r: Result[int, str] - reveal_type(RequiresContextFutureResult.from_result(r)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[Any, builtins.int*, builtins.str*]' + reveal_type(RequiresContextFutureResult.from_result(r)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.int*, builtins.str*, Any]' - case: requires_context_future_result_io @@ -44,7 +44,7 @@ r: IO[int] - reveal_type(RequiresContextFutureResult.from_io(r)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[Any, builtins.int*, Any]' + reveal_type(RequiresContextFutureResult.from_io(r)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.int*, Any, Any]' - case: requires_context_future_result_failed_io @@ -55,7 +55,7 @@ r: IO[int] - reveal_type(RequiresContextFutureResult.from_failed_io(r)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[Any, Any, builtins.int*]' + reveal_type(RequiresContextFutureResult.from_failed_io(r)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[Any, builtins.int*, Any]' - case: requires_context_future_result_ioresult @@ -66,7 +66,7 @@ r: IOResult[int, str] - reveal_type(RequiresContextFutureResult.from_ioresult(r)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[Any, builtins.int*, builtins.str*]' + reveal_type(RequiresContextFutureResult.from_ioresult(r)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.int*, builtins.str*, Any]' - case: requires_context_future_result_future @@ -77,7 +77,7 @@ r: Future[int] - reveal_type(RequiresContextFutureResult.from_future(r)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[Any, builtins.int*, Any]' + reveal_type(RequiresContextFutureResult.from_future(r)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.int*, Any, Any]' - case: requires_context_future_result_failed_future @@ -88,7 +88,7 @@ r: Future[int] - reveal_type(RequiresContextFutureResult.from_failed_future(r)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[Any, Any, builtins.int*]' + reveal_type(RequiresContextFutureResult.from_failed_future(r)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[Any, builtins.int*, Any]' - case: requires_context_future_result_future_result @@ -99,7 +99,7 @@ r: FutureResult[int, str] - reveal_type(RequiresContextFutureResult.from_future_result(r)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[Any, builtins.int*, builtins.str*]' + reveal_type(RequiresContextFutureResult.from_future_result(r)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.int*, builtins.str*, Any]' - case: requires_context_future_result_typecast @@ -108,9 +108,9 @@ from returns.context import RequiresContextFutureResult, RequiresContext from returns.future import FutureResult - r: RequiresContext[float, FutureResult[int, str]] + r: RequiresContext[FutureResult[int, str], float] - reveal_type(RequiresContextFutureResult.from_typecast(r)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.float*, builtins.int*, builtins.str*]' + reveal_type(RequiresContextFutureResult.from_typecast(r)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.int*, builtins.str*, builtins.float*]' - case: requires_context_future_result_successful_context @@ -118,9 +118,9 @@ main: | from returns.context import RequiresContextFutureResult, RequiresContext - r: RequiresContext[float, str] + r: RequiresContext[str, float] - reveal_type(RequiresContextFutureResult.from_context(r)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.float*, builtins.str*, Any]' + reveal_type(RequiresContextFutureResult.from_context(r)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.str*, Any, builtins.float*]' - case: requires_context_future_result_failed_context @@ -128,9 +128,9 @@ main: | from returns.context import RequiresContextFutureResult, RequiresContext - r: RequiresContext[float, str] + r: RequiresContext[str, float] - reveal_type(RequiresContextFutureResult.from_failed_context(r)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.float*, Any, builtins.str*]' + reveal_type(RequiresContextFutureResult.from_failed_context(r)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[Any, builtins.str*, builtins.float*]' - case: requires_context_future_result_from_result_context @@ -138,9 +138,9 @@ main: | from returns.context import RequiresContextFutureResult, RequiresContextResult - r: RequiresContextResult[float, int, str] + r: RequiresContextResult[int, str, float] - reveal_type(RequiresContextFutureResult.from_result_context(r)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.float*, builtins.int*, builtins.str*]' + reveal_type(RequiresContextFutureResult.from_result_context(r)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.int*, builtins.str*, builtins.float*]' - case: requires_context_future_result_from_ioresult_context @@ -148,6 +148,6 @@ main: | from returns.context import RequiresContextFutureResult, RequiresContextIOResult - r: RequiresContextIOResult[float, int, str] + r: RequiresContextIOResult[int, str, float] - reveal_type(RequiresContextFutureResult.from_ioresult_context(r)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.float*, builtins.int*, builtins.str*]' + reveal_type(RequiresContextFutureResult.from_ioresult_context(r)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.int*, builtins.str*, builtins.float*]' diff --git a/typesafety/test_context/test_requires_context_ioresult/test_context_ioresult.yml b/typesafety/test_context/test_requires_context_ioresult/test_context_ioresult.yml index af7caa5ea..c38537e65 100644 --- a/typesafety/test_context/test_requires_context_ioresult/test_context_ioresult.yml +++ b/typesafety/test_context/test_requires_context_ioresult/test_context_ioresult.yml @@ -3,7 +3,7 @@ main: | from returns.context import ContextIOResult - reveal_type(ContextIOResult.ask()) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[, , Any]' + reveal_type(ContextIOResult.ask()) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[, Any, ]' - case: context_result_io_ask2 @@ -11,4 +11,4 @@ main: | from returns.context import ContextIOResult - reveal_type(ContextIOResult[str].ask()) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.str*, builtins.str*, Any]' + reveal_type(ContextIOResult[str].ask()) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.str*, Any, builtins.str*]' diff --git a/typesafety/test_context/test_requires_context_ioresult/test_requires_context_ioresult.yml b/typesafety/test_context/test_requires_context_ioresult/test_requires_context_ioresult.yml index b68e729ad..fc1625c31 100644 --- a/typesafety/test_context/test_requires_context_ioresult/test_requires_context_ioresult.yml +++ b/typesafety/test_context/test_requires_context_ioresult/test_requires_context_ioresult.yml @@ -1,14 +1,24 @@ +- case: requires_context_ioresult_call + disable_cache: true + main: | + from returns.context import RequiresContextIOResult + + x: RequiresContextIOResult[int, float, str] + + reveal_type(x('a')) # N: Revealed type is 'returns.io.IOResult[builtins.int*, builtins.float*]' + + - case: requires_context_ioresult_bind disable_cache: true main: | from returns.context import RequiresContextIOResult - x: RequiresContextIOResult[str, int, float] + x: RequiresContextIOResult[int, float, str] - def test(param: int) -> RequiresContextIOResult[str, bool, float]: + def test(param: int) -> RequiresContextIOResult[bool, float, str]: ... - reveal_type(x.bind(test)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.str, builtins.bool*, builtins.float]' + reveal_type(x.bind(test)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.bool*, builtins.float, builtins.str]' - case: requires_context_ioresult_bind_result @@ -17,12 +27,12 @@ from returns.context import RequiresContextIOResult from returns.result import Result - x: RequiresContextIOResult[str, int, float] + x: RequiresContextIOResult[int, float, str] def test(param: int) -> Result[bool, float]: ... - reveal_type(x.bind_result(test)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.str, builtins.bool*, builtins.float]' + reveal_type(x.bind_result(test)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.bool*, builtins.float, builtins.str]' - case: requires_context_ioresult_bind_ioresult @@ -31,12 +41,12 @@ from returns.context import RequiresContextIOResult from returns.io import IOResult - x: RequiresContextIOResult[str, int, float] + x: RequiresContextIOResult[int, float, str] def test(param: int) -> IOResult[bool, float]: ... - reveal_type(x.bind_ioresult(test)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.str, builtins.bool*, builtins.float]' + reveal_type(x.bind_ioresult(test)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.bool*, builtins.float, builtins.str]' - case: requires_context_ioresult_bind_io @@ -45,12 +55,12 @@ from returns.context import RequiresContextIOResult from returns.io import IO - x: RequiresContextIOResult[str, int, float] + x: RequiresContextIOResult[int, float, str] def test(param: int) -> IO[bool]: ... - reveal_type(x.bind_io(test)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.str, builtins.bool*, builtins.float]' + reveal_type(x.bind_io(test)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.bool*, builtins.float, builtins.str]' - case: requires_context_ioresult_bind_context @@ -58,12 +68,12 @@ main: | from returns.context import RequiresContextIOResult, RequiresContext - x: RequiresContextIOResult[str, int, float] + x: RequiresContextIOResult[int, float, str] - def test(param: int) -> RequiresContext[str, bool]: + def test(param: int) -> RequiresContext[bool, str]: ... - reveal_type(x.bind_context(test)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.str, builtins.bool*, builtins.float]' + reveal_type(x.bind_context(test)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.bool*, builtins.float, builtins.str]' @@ -72,12 +82,12 @@ main: | from returns.context import RequiresContextIOResult, RequiresContextResult - x: RequiresContextIOResult[str, int, float] + x: RequiresContextIOResult[int, float, str] - def test(param: int) -> RequiresContextResult[str, bool, float]: + def test(param: int) -> RequiresContextResult[bool, float, str]: ... - reveal_type(x.bind_context_result(test)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.str, builtins.bool*, builtins.float]' + reveal_type(x.bind_context_result(test)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.bool*, builtins.float, builtins.str]' - case: requires_context_ioresult_map @@ -85,9 +95,9 @@ main: | from returns.context import RequiresContextIOResult - x: RequiresContextIOResult[str, int, float] + x: RequiresContextIOResult[int, float, str] - reveal_type(x.map(bool)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.str, builtins.bool*, builtins.float]' + reveal_type(x.map(bool)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.bool*, builtins.float, builtins.str]' - case: requires_context_ioresult_apply @@ -96,10 +106,10 @@ from typing import Callable from returns.context import RequiresContextIOResult - x: RequiresContextIOResult[str, int, float] - y: RequiresContextIOResult[str, Callable[[int], bool], float] + x: RequiresContextIOResult[int, float, str] + y: RequiresContextIOResult[Callable[[int], bool], float, str] - reveal_type(x.apply(y)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.str, builtins.bool*, builtins.float]' + reveal_type(x.apply(y)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.bool*, builtins.float, builtins.str]' - case: requires_context_ioresult_rescue @@ -107,12 +117,12 @@ main: | from returns.context import RequiresContextIOResult - x: RequiresContextIOResult[str, int, float] + x: RequiresContextIOResult[int, float, str] - def test(param: float) -> RequiresContextIOResult[str, int, bool]: + def test(param: float) -> RequiresContextIOResult[int, bool, str]: ... - reveal_type(x.rescue(test)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.str, builtins.int, builtins.bool*]' + reveal_type(x.rescue(test)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.int, builtins.bool*, builtins.str]' - case: requires_context_ioresult_fix @@ -120,12 +130,12 @@ main: | from returns.context import RequiresContextIOResult - x: RequiresContextIOResult[str, int, float] + x: RequiresContextIOResult[int, float, str] def test(param: float) -> bool: ... - reveal_type(x.fix(test)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.str, builtins.bool*, builtins.float]' + reveal_type(x.fix(test)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.bool*, builtins.float, builtins.str]' - case: requires_context_ioresult_alt @@ -133,39 +143,9 @@ main: | from returns.context import RequiresContextIOResult - x: RequiresContextIOResult[str, int, float] + x: RequiresContextIOResult[int, float, str] def test(param: float) -> bool: ... - reveal_type(x.alt(test)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.str, builtins.int, builtins.bool*]' - - -- case: requires_context_ioresult_value_or - disable_cache: true - main: | - from returns.context import RequiresContextIOResult - - x: RequiresContextIOResult[str, int, float] - - reveal_type(x.value_or(None)('a')) # N: Revealed type is 'returns.io.IO[Union[builtins.int, None]]' - - -- case: requires_context_ioresult_unwrap - disable_cache: true - main: | - from returns.context import RequiresContextIOResult - - x: RequiresContextIOResult[str, int, float] - - reveal_type(x.unwrap()('a')) # N: Revealed type is 'returns.io.IO[builtins.int*]' - - -- case: requires_context_ioresult_failure - disable_cache: true - main: | - from returns.context import RequiresContextIOResult - - x: RequiresContextIOResult[str, int, float] - - reveal_type(x.failure()('a')) # N: Revealed type is 'returns.io.IO[builtins.float*]' + reveal_type(x.alt(test)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.int, builtins.bool*, builtins.str]' diff --git a/typesafety/test_context/test_requires_context_ioresult/test_requires_context_ioresult_aliases.yml b/typesafety/test_context/test_requires_context_ioresult/test_requires_context_ioresult_aliases.yml new file mode 100644 index 000000000..9df4e2e63 --- /dev/null +++ b/typesafety/test_context/test_requires_context_ioresult/test_requires_context_ioresult_aliases.yml @@ -0,0 +1,15 @@ +- case: requires_context_ioresult_aliases + disable_cache: true + main: | + from returns.context import ( + RequiresContextIOResult, + RequiresContextIOResultE, + ReaderIOResult, + ReaderIOResultE, + ) + + x: RequiresContextIOResult[int, Exception, str] + + x1: RequiresContextIOResultE[int, str] = x + x2: ReaderIOResult[int, Exception, str] = x + x3: ReaderIOResultE[int, str] = x diff --git a/typesafety/test_context/test_requires_context_ioresult/test_requires_context_ioresult_cast.yml b/typesafety/test_context/test_requires_context_ioresult/test_requires_context_ioresult_cast.yml index 60c87f067..977692405 100644 --- a/typesafety/test_context/test_requires_context_ioresult/test_requires_context_ioresult_cast.yml +++ b/typesafety/test_context/test_requires_context_ioresult/test_requires_context_ioresult_cast.yml @@ -3,8 +3,8 @@ main: | from returns.context import RequiresContextIOResult - first: RequiresContextIOResult[str, object, Exception] = RequiresContextIOResult.from_value(1) - reveal_type(first) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.str, builtins.object, builtins.Exception]' + first: RequiresContextIOResult[object, Exception, str] = RequiresContextIOResult.from_value(1) + reveal_type(first) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.object, builtins.Exception, builtins.str]' - case: requires_context_ioresult_failure_cast @@ -12,8 +12,8 @@ main: | from returns.context import RequiresContextIOResult - first: RequiresContextIOResult[str, object, Exception] = RequiresContextIOResult.from_failure(TypeError()) - reveal_type(first) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.str, builtins.object, builtins.Exception]' + first: RequiresContextIOResult[object, Exception, str] = RequiresContextIOResult.from_failure(TypeError()) + reveal_type(first) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.object, builtins.Exception, builtins.str]' - case: requires_context_ioresult_env_cast @@ -21,7 +21,18 @@ main: | from returns.context import RequiresContextIOResult - first: RequiresContextIOResult[object, object, Exception] - second: RequiresContextIOResult[str, object, Exception] = first + first: RequiresContextIOResult[object, Exception, object] + second: RequiresContextIOResult[object, Exception, str] = first - reveal_type(second) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.str, builtins.object, builtins.Exception]' + reveal_type(second) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.object, builtins.Exception, builtins.str]' + + +- case: requires_context_ioresult_wrong_cast + disable_cache: true + main: | + from returns.context import RequiresContextIOResult + + first: RequiresContextIOResult[ValueError, TypeError, IndexError] + second: RequiresContextIOResult[Exception, Exception, Exception] = first + out: | + main:4: error: Incompatible types in assignment (expression has type "RequiresContextIOResult[ValueError, TypeError, IndexError]", variable has type "RequiresContextIOResult[Exception, Exception, Exception]") diff --git a/typesafety/test_context/test_requires_context_ioresult/test_requires_context_ioresult_unit.yml b/typesafety/test_context/test_requires_context_ioresult/test_requires_context_ioresult_unit.yml index c3692e6ed..4460fad04 100644 --- a/typesafety/test_context/test_requires_context_ioresult/test_requires_context_ioresult_unit.yml +++ b/typesafety/test_context/test_requires_context_ioresult/test_requires_context_ioresult_unit.yml @@ -3,7 +3,7 @@ main: | from returns.context import RequiresContextIOResult - reveal_type(RequiresContextIOResult.from_value(1)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[Any, builtins.int*, Any]' + reveal_type(RequiresContextIOResult.from_value(1)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.int*, Any, Any]' - case: requires_context_ioresult_failure @@ -11,7 +11,7 @@ main: | from returns.context import RequiresContextIOResult - reveal_type(RequiresContextIOResult.from_failure(1)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[Any, Any, builtins.int*]' + reveal_type(RequiresContextIOResult.from_failure(1)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[Any, builtins.int*, Any]' - case: requires_context_ioresult_from_iterable @@ -20,9 +20,9 @@ from returns.context import RequiresContextIOResult from typing import Iterable - x: Iterable[RequiresContextIOResult[str, int, float]] + x: Iterable[RequiresContextIOResult[int, float, str]] - reveal_type(RequiresContextIOResult.from_iterable(x)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.str*, typing.Sequence[builtins.int*], builtins.float*]' + reveal_type(RequiresContextIOResult.from_iterable(x)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[typing.Sequence[builtins.int*], builtins.float*, builtins.str*]' - case: requires_context_ioresult_result @@ -33,7 +33,7 @@ r: Result[int, str] - reveal_type(RequiresContextIOResult.from_result(r)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[Any, builtins.int*, builtins.str*]' + reveal_type(RequiresContextIOResult.from_result(r)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.int*, builtins.str*, Any]' - case: requires_context_ioresult_io @@ -44,7 +44,7 @@ r: IO[int] - reveal_type(RequiresContextIOResult.from_io(r)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[Any, builtins.int*, Any]' + reveal_type(RequiresContextIOResult.from_io(r)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.int*, Any, Any]' - case: requires_context_ioresult_failed_io @@ -55,7 +55,7 @@ r: IO[int] - reveal_type(RequiresContextIOResult.from_failed_io(r)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[Any, Any, builtins.int*]' + reveal_type(RequiresContextIOResult.from_failed_io(r)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[Any, builtins.int*, Any]' - case: requires_context_ioresult_ioresult @@ -66,7 +66,7 @@ r: IOResult[int, str] - reveal_type(RequiresContextIOResult.from_ioresult(r)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[Any, builtins.int*, builtins.str*]' + reveal_type(RequiresContextIOResult.from_ioresult(r)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.int*, builtins.str*, Any]' - case: requires_context_ioresult_typecast @@ -75,9 +75,9 @@ from returns.context import RequiresContextIOResult, RequiresContext from returns.io import IOResult - r: RequiresContext[float, IOResult[int, str]] + r: RequiresContext[IOResult[int, str], float] - reveal_type(RequiresContextIOResult.from_typecast(r)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.float*, builtins.int*, builtins.str*]' + reveal_type(RequiresContextIOResult.from_typecast(r)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.int*, builtins.str*, builtins.float*]' - case: requires_context_ioresult_successful_context @@ -85,9 +85,9 @@ main: | from returns.context import RequiresContextIOResult, RequiresContext - r: RequiresContext[float, str] + r: RequiresContext[str, float] - reveal_type(RequiresContextIOResult.from_context(r)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.float*, builtins.str*, Any]' + reveal_type(RequiresContextIOResult.from_context(r)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.str*, Any, builtins.float*]' - case: requires_context_ioresult_failed_context @@ -95,9 +95,9 @@ main: | from returns.context import RequiresContextIOResult, RequiresContext - r: RequiresContext[float, str] + r: RequiresContext[str, float] - reveal_type(RequiresContextIOResult.from_failed_context(r)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.float*, Any, builtins.str*]' + reveal_type(RequiresContextIOResult.from_failed_context(r)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[Any, builtins.str*, builtins.float*]' - case: requires_context_ioresult_from_result_context @@ -105,6 +105,6 @@ main: | from returns.context import RequiresContextIOResult, RequiresContextResult - r: RequiresContextResult[float, int, str] + r: RequiresContextResult[int, str, float] - reveal_type(RequiresContextIOResult.from_result_context(r)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.float*, builtins.int*, builtins.str*]' + reveal_type(RequiresContextIOResult.from_result_context(r)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.int*, builtins.str*, builtins.float*]' diff --git a/typesafety/test_context/test_requires_context_result/test_context_result.yml b/typesafety/test_context/test_requires_context_result/test_context_result.yml index bff5043e3..d9c7cdec3 100644 --- a/typesafety/test_context/test_requires_context_result/test_context_result.yml +++ b/typesafety/test_context/test_requires_context_result/test_context_result.yml @@ -3,7 +3,7 @@ main: | from returns.context import ContextResult - reveal_type(ContextResult.ask()) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[, , Any]' + reveal_type(ContextResult.ask()) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[, Any, ]' - case: context_ask2 @@ -11,4 +11,4 @@ main: | from returns.context import ContextResult - reveal_type(ContextResult[str].ask()) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.str*, builtins.str*, Any]' + reveal_type(ContextResult[str].ask()) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.str*, Any, builtins.str*]' diff --git a/typesafety/test_context/test_requires_context_result/test_requires_context_cast.yml b/typesafety/test_context/test_requires_context_result/test_requires_context_cast.yml index 7dfd959bc..91497ace5 100644 --- a/typesafety/test_context/test_requires_context_result/test_requires_context_cast.yml +++ b/typesafety/test_context/test_requires_context_result/test_requires_context_cast.yml @@ -3,8 +3,8 @@ main: | from returns.context import RequiresContextResult - first: RequiresContextResult[str, object, Exception] = RequiresContextResult.from_value(1) - reveal_type(first) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.str, builtins.object, builtins.Exception]' + first: RequiresContextResult[object, Exception, str] = RequiresContextResult.from_value(1) + reveal_type(first) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.object, builtins.Exception, builtins.str]' - case: requires_context_result_failure_cast @@ -12,8 +12,8 @@ main: | from returns.context import RequiresContextResult - first: RequiresContextResult[str, object, Exception] = RequiresContextResult.from_failure(TypeError()) - reveal_type(first) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.str, builtins.object, builtins.Exception]' + first: RequiresContextResult[object, Exception, str] = RequiresContextResult.from_failure(TypeError()) + reveal_type(first) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.object, builtins.Exception, builtins.str]' - case: requires_context_result_env_cast @@ -21,7 +21,18 @@ main: | from returns.context import RequiresContextResult - first: RequiresContextResult[object, object, Exception] - second: RequiresContextResult[str, object, Exception] = first + first: RequiresContextResult[object, Exception, object] + second: RequiresContextResult[object, Exception, str] = first - reveal_type(second) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.str, builtins.object, builtins.Exception]' + reveal_type(second) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.object, builtins.Exception, builtins.str]' + + +- case: requires_context_result_wrong_cast + disable_cache: true + main: | + from returns.context import RequiresContextResult + + first: RequiresContextResult[ValueError, TypeError, IndexError] + second: RequiresContextResult[Exception, Exception, Exception] = first + out: | + main:4: error: Incompatible types in assignment (expression has type "RequiresContextResult[ValueError, TypeError, IndexError]", variable has type "RequiresContextResult[Exception, Exception, Exception]") diff --git a/typesafety/test_context/test_requires_context_result/test_requires_context_result.yml b/typesafety/test_context/test_requires_context_result/test_requires_context_result.yml index 275428831..5079fe1c1 100644 --- a/typesafety/test_context/test_requires_context_result/test_requires_context_result.yml +++ b/typesafety/test_context/test_requires_context_result/test_requires_context_result.yml @@ -1,14 +1,24 @@ +- case: requires_context_result_call + disable_cache: true + main: | + from returns.context import RequiresContextResult + + x: RequiresContextResult[int, Exception, str] + + reveal_type(x('a')) # N: Revealed type is 'returns.result.Result[builtins.int*, builtins.Exception*]' + + - case: requires_context_result_bind disable_cache: true main: | from returns.context import RequiresContextResult - x: RequiresContextResult[str, int, float] + x: RequiresContextResult[int, float, str] - def test(param: int) -> RequiresContextResult[str, bool, float]: + def test(param: int) -> RequiresContextResult[bool, float, str]: ... - reveal_type(x.bind(test)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.str, builtins.bool*, builtins.float]' + reveal_type(x.bind(test)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.bool*, builtins.float, builtins.str]' - case: requires_context_result_bind_result @@ -17,12 +27,12 @@ from returns.context import RequiresContextResult from returns.result import Result - x: RequiresContextResult[str, int, float] + x: RequiresContextResult[int, float, str] def test(param: int) -> Result[bool, float]: ... - reveal_type(x.bind_result(test)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.str, builtins.bool*, builtins.float]' + reveal_type(x.bind_result(test)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.bool*, builtins.float, builtins.str]' - case: requires_context_result_bind_context @@ -30,12 +40,12 @@ main: | from returns.context import RequiresContextResult, RequiresContext - x: RequiresContextResult[str, int, float] + x: RequiresContextResult[int, float, str] - def test(param: int) -> RequiresContext[str, bool]: + def test(param: int) -> RequiresContext[bool, str]: ... - reveal_type(x.bind_context(test)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.str, builtins.bool*, builtins.float]' + reveal_type(x.bind_context(test)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.bool*, builtins.float, builtins.str]' - case: requires_context_result_map @@ -43,9 +53,9 @@ main: | from returns.context import RequiresContextResult - x: RequiresContextResult[str, int, float] + x: RequiresContextResult[int, float, str] - reveal_type(x.map(bool)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.str, builtins.bool*, builtins.float]' + reveal_type(x.map(bool)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.bool*, builtins.float, builtins.str]' - case: requires_context_result_apply @@ -54,10 +64,10 @@ from typing import Callable from returns.context import RequiresContextResult - x: RequiresContextResult[str, int, float] - y: RequiresContextResult[str, Callable[[int], bool], float] + x: RequiresContextResult[int, float, str] + y: RequiresContextResult[Callable[[int], bool], float, str] - reveal_type(x.apply(y)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.str, builtins.bool*, builtins.float]' + reveal_type(x.apply(y)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.bool*, builtins.float, builtins.str]' - case: requires_context_result_rescue @@ -65,12 +75,12 @@ main: | from returns.context import RequiresContextResult - x: RequiresContextResult[str, int, float] + x: RequiresContextResult[int, float, str] - def test(param: float) -> RequiresContextResult[str, int, bool]: + def test(param: float) -> RequiresContextResult[int, bool, str]: ... - reveal_type(x.rescue(test)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.str, builtins.int, builtins.bool*]' + reveal_type(x.rescue(test)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.int, builtins.bool*, builtins.str]' - case: requires_context_result_fix @@ -78,12 +88,12 @@ main: | from returns.context import RequiresContextResult - x: RequiresContextResult[str, int, float] + x: RequiresContextResult[int, float, str] def test(param: float) -> bool: ... - reveal_type(x.fix(test)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.str, builtins.bool*, builtins.float]' + reveal_type(x.fix(test)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.bool*, builtins.float, builtins.str]' - case: requires_context_result_alt @@ -91,39 +101,9 @@ main: | from returns.context import RequiresContextResult - x: RequiresContextResult[str, int, float] + x: RequiresContextResult[int, float, str] def test(param: float) -> bool: ... - reveal_type(x.alt(test)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.str, builtins.int, builtins.bool*]' - - -- case: requires_context_result_value_or - disable_cache: true - main: | - from returns.context import RequiresContextResult - - x: RequiresContextResult[str, int, float] - - reveal_type(x.value_or(None)('a')) # N: Revealed type is 'Union[builtins.int, None]' - - -- case: requires_context_result_unwrap - disable_cache: true - main: | - from returns.context import RequiresContextResult - - x: RequiresContextResult[str, int, float] - - reveal_type(x.unwrap()('a')) # N: Revealed type is 'builtins.int*' - - -- case: requires_context_result_failure - disable_cache: true - main: | - from returns.context import RequiresContextResult - - x: RequiresContextResult[str, int, float] - - reveal_type(x.failure()('a')) # N: Revealed type is 'builtins.float*' + reveal_type(x.alt(test)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.int, builtins.bool*, builtins.str]' diff --git a/typesafety/test_context/test_requires_context_result/test_requires_context_result_unit.yml b/typesafety/test_context/test_requires_context_result/test_requires_context_result_unit.yml index 1f43e6543..4c49d32a1 100644 --- a/typesafety/test_context/test_requires_context_result/test_requires_context_result_unit.yml +++ b/typesafety/test_context/test_requires_context_result/test_requires_context_result_unit.yml @@ -3,7 +3,7 @@ main: | from returns.context import RequiresContextResult - reveal_type(RequiresContextResult.from_value(1)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[Any, builtins.int*, Any]' + reveal_type(RequiresContextResult.from_value(1)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.int*, Any, Any]' - case: requires_context_result_failure @@ -11,7 +11,7 @@ main: | from returns.context import RequiresContextResult - reveal_type(RequiresContextResult.from_failure(1)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[Any, Any, builtins.int*]' + reveal_type(RequiresContextResult.from_failure(1)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[Any, builtins.int*, Any]' - case: requires_context_result_from_iterable @@ -20,9 +20,9 @@ from returns.context import RequiresContextResult from typing import Iterable - x: Iterable[RequiresContextResult[str, int, float]] + x: Iterable[RequiresContextResult[int, float, str]] - reveal_type(RequiresContextResult.from_iterable(x)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.str*, typing.Sequence[builtins.int*], builtins.float*]' + reveal_type(RequiresContextResult.from_iterable(x)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[typing.Sequence[builtins.int*], builtins.float*, builtins.str*]' - case: requires_context_result_result @@ -33,7 +33,7 @@ r: Result[int, str] - reveal_type(RequiresContextResult.from_result(r)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[Any, builtins.int*, builtins.str*]' + reveal_type(RequiresContextResult.from_result(r)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.int*, builtins.str*, Any]' - case: requires_context_result_typecast @@ -42,9 +42,9 @@ from returns.context import RequiresContextResult, RequiresContext from returns.result import Result - r: RequiresContext[float, Result[int, str]] + r: RequiresContext[Result[int, str], float] - reveal_type(RequiresContextResult.from_typecast(r)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.float*, builtins.int*, builtins.str*]' + reveal_type(RequiresContextResult.from_typecast(r)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.int*, builtins.str*, builtins.float*]' - case: requires_context_result_successful_context @@ -52,9 +52,9 @@ main: | from returns.context import RequiresContextResult, RequiresContext - r: RequiresContext[float, str] + r: RequiresContext[str, float] - reveal_type(RequiresContextResult.from_context(r)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.float*, builtins.str*, Any]' + reveal_type(RequiresContextResult.from_context(r)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.str*, Any, builtins.float*]' - case: requires_context_result_failed_context @@ -62,6 +62,6 @@ main: | from returns.context import RequiresContextResult, RequiresContext - r: RequiresContext[float, str] + r: RequiresContext[str, float] - reveal_type(RequiresContextResult.from_failed_context(r)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.float*, Any, builtins.str*]' + reveal_type(RequiresContextResult.from_failed_context(r)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[Any, builtins.str*, builtins.float*]' diff --git a/typesafety/test_future/test_future_result_container/test_future_result_base.yml b/typesafety/test_future/test_future_result_container/test_future_result_base.yml index 60f72f0fc..24042bb2d 100644 --- a/typesafety/test_future/test_future_result_container/test_future_result_base.yml +++ b/typesafety/test_future/test_future_result_container/test_future_result_base.yml @@ -156,33 +156,3 @@ first: FutureResult[int, str] reveal_type(first.rescue(bind)) # N: Revealed type is 'returns.future.FutureResult[builtins.int, builtins.float*]' - - -- case: future_result_value_or - disable_cache: true - main: | - from returns.future import FutureResult - - first: FutureResult[int, bool] - - reveal_type(first.value_or('a')) # N: Revealed type is 'typing.Awaitable[returns.io.IO[Union[builtins.int, builtins.str*]]]' - - -- case: future_result_unwrap - disable_cache: true - main: | - from returns.future import FutureResult - - first: FutureResult[int, str] - - reveal_type(first.unwrap()) # N: Revealed type is 'typing.Awaitable[returns.io.IO[builtins.int*]]' - - -- case: future_result_failure - disable_cache: true - main: | - from returns.future import FutureResult - - first: FutureResult[int, str] - - reveal_type(first.failure()) # N: Revealed type is 'typing.Awaitable[returns.io.IO[builtins.str*]]' diff --git a/typesafety/test_interfaces/test_applicative/test_inheritance.yml b/typesafety/test_interfaces/test_applicative/test_inheritance.yml new file mode 100644 index 000000000..0c3495d36 --- /dev/null +++ b/typesafety/test_interfaces/test_applicative/test_inheritance.yml @@ -0,0 +1,135 @@ +- case: applicative_inheritance_correct1 + disable_cache: true + main: | + from typing import Callable, TypeVar + from returns.interfaces.applicative import Applicative1 + from returns.primitives.hkt import Kind1, dekind + + V = TypeVar('V') + N = TypeVar('N') + + class MyClass(Kind1['MyClass', V], Applicative1[V]): + def __init__(self, value: V) -> None: + self.value = value + + def apply( + self, + container: Kind1['MyClass', Callable[[V], N]], + ) -> 'MyClass[N]': + return MyClass(dekind(container).value(self.value)) + + @classmethod + def from_value(cls, inner_value: N) -> MyClass[N]: + return MyClass(inner_value) + + reveal_type(MyClass('1').apply(MyClass.from_value(int))) # N: Revealed type is 'main.MyClass[builtins.int*]' + + +- case: applicative_inheritance_correct2 + disable_cache: true + main: | + from typing import Any, Callable, TypeVar + from returns.interfaces.applicative import Applicative2 + from returns.primitives.hkt import Kind2, dekind + + V = TypeVar('V') + E = TypeVar('E') + N = TypeVar('N') + + class MyClass(Kind2['MyClass', V, E], Applicative2[V, E]): + def __init__(self, value: V, error: E) -> None: + self.value = value + self.error = error + + def apply( + self, + container: Kind2['MyClass', Callable[[V], N], E], + ) -> 'MyClass[N, E]': + return MyClass(dekind(container).value(self.value), self.error) + + @classmethod + def from_value(cls, inner_value: N) -> MyClass[N, Any]: + return MyClass(inner_value, None) + + reveal_type(MyClass('1', True).apply(MyClass.from_value(int))) # N: Revealed type is 'main.MyClass[builtins.int*, builtins.bool]' + + +- case: applicative_inheritance_correct2 + disable_cache: true + main: | + from typing import Any, Callable, TypeVar + from returns.interfaces.applicative import Applicative3 + from returns.primitives.hkt import Kind3, dekind + + V = TypeVar('V') + E = TypeVar('E') + T = TypeVar('T') + N = TypeVar('N') + + class MyClass(Kind3['MyClass', V, E, T], Applicative3[V, E, T]): + def __init__(self, value: V, error: E, last: T) -> None: + self.value = value + self.error = error + self.last = last + + def apply( + self, + container: Kind3['MyClass', Callable[[V], N], E, T], + ) -> 'MyClass[N, E, T]': + return MyClass(dekind(container).value(self.value), self.error, self.last) + + @classmethod + def from_value(cls, inner_value: N) -> MyClass[N, Any, Any]: + return MyClass(inner_value, None, None) + + reveal_type(MyClass('1', True, 'a').apply(MyClass.from_value(int))) # N: Revealed type is 'main.MyClass[builtins.int*, builtins.bool, builtins.str]' + + +- case: applicative_inheritance_missing + disable_cache: true + main: | + from typing import Callable, TypeVar + from returns.interfaces.applicative import Applicative1 + from returns.primitives.hkt import Kind1 + + V = TypeVar('V') + N = TypeVar('N') + + class MyClass(Kind1['MyClass', V], Applicative1[V]): + def __init__(self, value: V) -> None: + self.value = value + + reveal_type(MyClass('1')) + out: | + main:12: error: Cannot instantiate abstract class 'MyClass' with abstract attributes 'apply' and 'from_value' + main:12: note: Revealed type is 'main.MyClass[builtins.str*]' + + +- case: applicative_inheritance_wrong + disable_cache: true + main: | + from typing import Callable, TypeVar + from returns.interfaces.applicative import Applicative1 + from returns.primitives.hkt import Kind1, dekind + + V = TypeVar('V') + N = TypeVar('N') + + class MyClass(Kind1['MyClass', V], Applicative1[V]): + def __init__(self, value: V) -> None: + self.value = value + + def apply( + self, + container: 'MyClass[Callable[[V], N]]', + ) -> 'MyClass[N]': + ... + + @classmethod + def from_value(cls, inner_value: V) -> None: + ... + out: | + main:12: error: Argument 1 of "apply" is incompatible with supertype "ApplicativeN"; supertype defines the argument type as "KindN[MyClass[V], Callable[[V], _UpdatedType], NoReturn, NoReturn]" + main:12: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides + main:12: note: This violates the Liskov substitution principle + main:19: error: Return type "None" of "from_value" incompatible with return type "KindN[MyClass[V], V, NoReturn, NoReturn]" in supertype "ApplicativeN" diff --git a/typesafety/test_interfaces/test_bindable/test_inheritance.yml b/typesafety/test_interfaces/test_bindable/test_inheritance.yml new file mode 100644 index 000000000..50f4f8654 --- /dev/null +++ b/typesafety/test_interfaces/test_bindable/test_inheritance.yml @@ -0,0 +1,128 @@ +- case: bindable_inheritance_correct1 + disable_cache: true + main: | + from typing import Callable, TypeVar + from returns.interfaces.bindable import Bindable1 + from returns.primitives.hkt import Kind1, dekind + + V = TypeVar('V') + N = TypeVar('N') + + class MyClass(Kind1['MyClass', V], Bindable1[V]): + def __init__(self, value: V) -> None: + self.value = value + + def bind( + self, + function: Callable[[V], Kind1['MyClass', N]], + ) -> 'MyClass[N]': + return dekind(function(self.value)) + + def test(arg: str) -> MyClass[int]: + return MyClass(int(arg)) + + reveal_type(MyClass('1').bind(test)) # N: Revealed type is 'main.MyClass[builtins.int*]' + + +- case: bindable_inheritance_correct2 + disable_cache: true + main: | + from typing import Callable, TypeVar + from returns.interfaces.bindable import Bindable2 + from returns.primitives.hkt import Kind2, dekind + + V = TypeVar('V') + T = TypeVar('T') + N = TypeVar('N') + + class MyClass(Kind2['MyClass', V, T], Bindable2[V, T]): + def __init__(self, value: V, other: T) -> None: + self.value = value + self.other = other + + def bind( + self, + function: Callable[[V], Kind2['MyClass', N, T]], + ) -> 'MyClass[N, T]': + return dekind(function(self.value)) + + def test(arg: str) -> MyClass[int, str]: + return MyClass(int(arg), 'a') + + reveal_type(MyClass('1', 'a').bind(test)) # N: Revealed type is 'main.MyClass[builtins.int*, builtins.str]' + + +- case: bindable_inheritance_correct3 + disable_cache: true + main: | + from typing import Callable, TypeVar + from returns.interfaces.bindable import Bindable3 + from returns.primitives.hkt import Kind3, dekind + + V = TypeVar('V') + T = TypeVar('T') + K = TypeVar('K') + N = TypeVar('N') + + class MyClass(Kind3['MyClass', V, T, K], Bindable3[V, T, K]): + def __init__(self, value: V, other: T, last: K) -> None: + self.value = value + self.other = other + self.last = last + + def bind( + self, + function: Callable[[V], Kind3['MyClass', N, T, K]], + ) -> 'MyClass[N, T, K]': + return dekind(function(self.value)) + + def test(arg: str) -> MyClass[int, str, bool]: + return MyClass(int(arg), 'a', True) + + reveal_type(MyClass('1', 'a', True).bind(test)) # N: Revealed type is 'main.MyClass[builtins.int*, builtins.str, builtins.bool]' + + +- case: bindable_inheritance_missing + disable_cache: true + main: | + from typing import Callable, TypeVar + from returns.interfaces.bindable import Bindable1 + from returns.primitives.hkt import Kind1, dekind + + V = TypeVar('V') + N = TypeVar('N') + + class MyClass(Kind1['MyClass', V], Bindable1[V]): + def __init__(self, value: V) -> None: + self.value = value + + reveal_type(MyClass('1')) + out: | + main:12: error: Cannot instantiate abstract class 'MyClass' with abstract attribute 'bind' + main:12: note: Revealed type is 'main.MyClass[builtins.str*]' + + +- case: bindable_inheritance_wrong + disable_cache: true + main: | + from typing import Callable, TypeVar + from returns.interfaces.bindable import Bindable1 + from returns.primitives.hkt import Kind1, dekind + + V = TypeVar('V') + N = TypeVar('N') + + class MyClass(Kind1['MyClass', V], Bindable1[V]): + def __init__(self, value: V) -> None: + self.value = value + + def bind( + self, + function: Callable[[V], Kind1['MyClass', V]], + ) -> 'MyClass[V]': + return dekind(function(self.value)) + out: | + main:12: error: Argument 1 of "bind" is incompatible with supertype "BindableN"; supertype defines the argument type as "Callable[[V], KindN[MyClass[V], _UpdatedType, NoReturn, NoReturn]]" + main:12: error: Return type "MyClass[V]" of "bind" incompatible with return type "KindN[MyClass[V], _UpdatedType, NoReturn, NoReturn]" in supertype "BindableN" + main:12: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides + main:12: note: This violates the Liskov substitution principle diff --git a/typesafety/test_interfaces/test_mappable/test_inheritance.yml b/typesafety/test_interfaces/test_mappable/test_inheritance.yml new file mode 100644 index 000000000..9f5a29c35 --- /dev/null +++ b/typesafety/test_interfaces/test_mappable/test_inheritance.yml @@ -0,0 +1,129 @@ +- case: mappable_inheritance_correct1 + disable_cache: true + main: | + from typing import Callable, TypeVar + from returns.interfaces.mappable import Mappable1 + from returns.primitives.hkt import Kind1 + + V = TypeVar('V') + N = TypeVar('N') + + class MyClass(Kind1['MyClass', V], Mappable1[V]): + def __init__(self, value: V) -> None: + self.value = value + + def map(self, function: Callable[[V], N]) -> 'MyClass[N]': + return MyClass(function(self.value)) + + reveal_type(MyClass('1').map(int)) # N: Revealed type is 'main.MyClass[builtins.int*]' + + +- case: mappable_inheritance_correct2 + disable_cache: true + main: | + from typing import Callable, TypeVar + from returns.interfaces.mappable import Mappable2 + from returns.primitives.hkt import Kind2 + + V = TypeVar('V') + E = TypeVar('E') + N = TypeVar('N') + + class MyClass(Kind2['MyClass', V, E], Mappable2[V, E]): + def __init__(self, value: V, error: E) -> None: + self.value = value + self.error = error + + def map(self, function: Callable[[V], N]) -> 'MyClass[N, E]': + return MyClass(function(self.value), self.error) + + reveal_type(MyClass('1', 1).map(int)) # N: Revealed type is 'main.MyClass[builtins.int*, builtins.int]' + + +- case: mappable_inheritance_correct3 + disable_cache: true + main: | + from typing import Callable, TypeVar + from returns.interfaces.mappable import Mappable3 + from returns.primitives.hkt import Kind3 + + V = TypeVar('V') + E = TypeVar('E') + K = TypeVar('K') + N = TypeVar('N') + + class MyClass(Kind3['MyClass', V, E, K], Mappable3[V, E, K]): + def __init__(self, value: V, error: E, last: K) -> None: + self.value = value + self.error = error + self.last = last + + def map(self, function: Callable[[V], N]) -> 'MyClass[N, E, K]': + return MyClass(function(self.value), self.error, self.last) + + reveal_type(MyClass('1', 1, True).map(int)) # N: Revealed type is 'main.MyClass[builtins.int*, builtins.int, builtins.bool]' + + +- case: mappable_inheritance_missing + disable_cache: true + main: | + from typing import Callable, TypeVar + from returns.interfaces.mappable import Mappable1 + from returns.primitives.hkt import Kind1 + + V = TypeVar('V') + N = TypeVar('N') + + class MyClass(Kind1['MyClass', V], Mappable1[V]): + def __init__(self, value: V) -> None: + self.value = value + + reveal_type(MyClass('1').map(int)) + out: | + main:12: error: Cannot instantiate abstract class 'MyClass' with abstract attribute 'map' + main:12: note: Revealed type is 'returns.primitives.hkt.KindN[main.MyClass[builtins.str], builtins.int*, , ]' + + +- case: mappable_inheritance_wrong + disable_cache: true + main: | + from typing import Callable, TypeVar + from returns.interfaces.mappable import Mappable1 + from returns.primitives.hkt import Kind1 + + V = TypeVar('V') + N = TypeVar('N') + + class MyClass(Kind1['MyClass', V], Mappable1[V]): + def __init__(self, value: V) -> None: + self.value = value + + # Breaks the contract + def map(self, function: Callable[[V], N]) -> 'MyClass[V]': + return MyClass(self.value) + out: | + main:13: error: Return type "MyClass[V]" of "map" incompatible with return type "KindN[MyClass[V], _UpdatedType, NoReturn, NoReturn]" in supertype "MappableN" + + +- case: mappable_inheritance_wrong2 + disable_cache: true + main: | + from typing import Callable, TypeVar + from returns.interfaces.mappable import Mappable2 + from returns.primitives.hkt import Kind2 + + V = TypeVar('V') + E = TypeVar('E') + N = TypeVar('N') + + class MyClass(Kind2['MyClass', V, E], Mappable2[V, E]): + def __init__(self, value: V, error: E) -> None: + self.value = value + self.error = error + + def map(self, function: Callable[[E], N]) -> 'MyClass[N, E]': + return MyClass(function(self.error), self.error) + out: | + main:14: error: Argument 1 of "map" is incompatible with supertype "MappableN"; supertype defines the argument type as "Callable[[V], _UpdatedType]" + main:14: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides + main:14: note: This violates the Liskov substitution principle diff --git a/typesafety/test_interfaces/test_rescuable/test_inheritance.yml b/typesafety/test_interfaces/test_rescuable/test_inheritance.yml new file mode 100644 index 000000000..56a64304d --- /dev/null +++ b/typesafety/test_interfaces/test_rescuable/test_inheritance.yml @@ -0,0 +1,104 @@ +- case: rescuable_inheritance_correct2 + disable_cache: true + main: | + from typing import Callable, TypeVar + from returns.interfaces.rescuable import Rescuable2 + from returns.primitives.hkt import Kind2, dekind + + V = TypeVar('V') + E = TypeVar('E') + N = TypeVar('N') + + class MyClass(Kind2['MyClass', V, E], Rescuable2[V, E]): + def __init__(self, value: V, error: E) -> None: + self.value = value + self.error = error + + def rescue( + self, + function: Callable[[E], Kind2['MyClass', V, N]], + ) -> 'MyClass[V, N]': + return dekind(function(self.error)) + + def test(arg: str) -> MyClass[int, int]: + ... + + reveal_type(MyClass(1, '1').rescue(test)) # N: Revealed type is 'main.MyClass[builtins.int, builtins.int*]' + + +- case: rescuable_inheritance_correct3 + disable_cache: true + main: | + from typing import Callable, TypeVar + from returns.interfaces.rescuable import Rescuable3 + from returns.primitives.hkt import Kind3, dekind + + V = TypeVar('V') + T = TypeVar('T') + K = TypeVar('K') + N = TypeVar('N') + + class MyClass(Kind3['MyClass', V, T, K], Rescuable3[V, T, K]): + def __init__(self, value: V, other: T, last: K) -> None: + self.value = value + self.other = other + self.last = last + + def rescue( + self, + function: Callable[[T], Kind3['MyClass', V, N, K]], + ) -> 'MyClass[V, N, K]': + return dekind(function(self.other)) + + def test(arg: str) -> MyClass[int, float, bool]: + ... + + reveal_type(MyClass(1, 'a', True).rescue(test)) # N: Revealed type is 'main.MyClass[builtins.int, builtins.float*, builtins.bool]' + + +- case: rescuable_inheritance_missing + disable_cache: true + main: | + from typing import Callable, TypeVar + from returns.interfaces.rescuable import Rescuable2 + from returns.primitives.hkt import Kind2, dekind + + V = TypeVar('V') + N = TypeVar('N') + + class MyClass(Kind2['MyClass', V], Rescuable2[V]): + def __init__(self, value: V) -> None: + self.value = value + + reveal_type(MyClass('1')) + out: | + main:8: error: Bad number of arguments for type alias, expected: 2, given: 1 + main:8: error: Bad number of arguments for type alias, expected: 3, given: 2 + main:12: error: Cannot instantiate abstract class 'MyClass' with abstract attribute 'rescue' + main:12: note: Revealed type is 'main.MyClass[builtins.str*]' + + +- case: rescuable_inheritance_wrong + disable_cache: true + main: | + from typing import Callable, TypeVar + from returns.interfaces.rescuable import Rescuable2 + from returns.primitives.hkt import Kind2, dekind + + V = TypeVar('V') + N = TypeVar('N') + E = TypeVar('E') + + class MyClass(Kind2['MyClass', V, E], Rescuable2[V, E]): + def __init__(self, value: V, error: E) -> None: + self.value = value + self.error = error + + def rescue( + self, + function: Callable[[E], Kind2['MyClass', N, N]], + ) -> 'MyClass[N, E]': + return dekind(function(self.error)) + out: | + main:14: error: Return type "MyClass[N, E]" of "rescue" incompatible with return type "KindN[MyClass[V, E], V, _UpdatedType, NoReturn]" in supertype "RescuableN" + main:18: error: Incompatible return value type (got "MyClass[N, N]", expected "MyClass[N, E]") diff --git a/typesafety/test_interfaces/test_specific/test_result/test_inheritance.yml b/typesafety/test_interfaces/test_specific/test_result/test_inheritance.yml new file mode 100644 index 000000000..d193b53d9 --- /dev/null +++ b/typesafety/test_interfaces/test_specific/test_result/test_inheritance.yml @@ -0,0 +1,110 @@ +- case: result_inheritance_correct + disable_cache: true + main: | + from typing import Callable, TypeVar, Any + from returns.interfaces.specific.result import ResultBased2 + from returns.primitives.hkt import Kind2 + from returns.result import Result + + _ValueType = TypeVar('_ValueType') + _NewValueType = TypeVar('_NewValueType') + + # Result related: + _ErrorType = TypeVar('_ErrorType') + _NewErrorType = TypeVar('_NewErrorType') + + class MyClass( + Kind2['MyClass', _ValueType, _ErrorType], + ResultBased2[_ValueType, _ErrorType], + ): + def bind_result( + self, + function: Callable[ + [_ValueType], + Result[_NewValueType, _ErrorType], + ], + ) -> MyClass[_NewValueType, _ErrorType]: + ... + + @classmethod + def from_result( + self, inner_value: Result[_NewValueType, _NewErrorType], + ) -> MyClass[_NewValueType, _NewErrorType]: + ... + + @classmethod + def from_failure( + cls, inner_value: _NewErrorType, + ) -> MyClass[Any, _NewErrorType]: + ... + + def test(a: int) -> Result[float, str]: + ... + + x: MyClass[int, str] + reveal_type(x.bind_result(test)) # N: Revealed type is 'main.MyClass[builtins.float*, builtins.str]' + + +- case: result_inheritance_missing + disable_cache: true + main: | + from typing import Callable, TypeVar + from returns.interfaces.specific.result import ResultBased2 + from returns.primitives.hkt import Kind2 + + V = TypeVar('V') + N = TypeVar('N') + + class MyClass(Kind2['MyClass', V, N], ResultBased2[V, N]): + ... + + MyClass() + out: | + main:11: error: Cannot instantiate abstract class 'MyClass' with abstract attributes 'bind_result', 'from_failure' and 'from_result' + + +- case: result_inheritance_wrong + disable_cache: true + main: | + from typing import Callable, TypeVar + from returns.interfaces.specific.result import ResultBased2 + from returns.primitives.hkt import Kind2 + from returns.result import Result + + _ValueType = TypeVar('_ValueType', covariant=True) + _NewValueType = TypeVar('_NewValueType') + + # Result related: + _ErrorType = TypeVar('_ErrorType', covariant=True) + _NewErrorType = TypeVar('_NewErrorType') + + class MyClass( + Kind2['MyClass', _ValueType, _ErrorType], + ResultBased2[_ValueType, _ErrorType], + ): + def bind_result( + self, + function: Callable[ + [_ValueType], + Result[_ValueType, _ErrorType], + ], + ) -> MyClass[_ValueType, _ErrorType]: + ... + + def from_result( + self, inner_value: Result[_NewValueType, _NewErrorType], + ) -> MyClass[_NewValueType, _NewErrorType]: + ... + + @classmethod + def from_failure( + cls, inner_value: _NewErrorType, + ) -> MyClass[_NewErrorType, _NewErrorType]: + ... + out: | + main:17: error: Argument 1 of "bind_result" is incompatible with supertype "ResultBasedN"; supertype defines the argument type as "Callable[[_ValueType], Result[_UpdatedType, _ErrorType]]" + main:17: error: Return type "MyClass[_ValueType, _ErrorType]" of "bind_result" incompatible with return type "KindN[MyClass[_ValueType, _ErrorType], _UpdatedType, _ErrorType, NoReturn]" in supertype "ResultBasedN" + main:17: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides + main:17: note: This violates the Liskov substitution principle + main:26: error: Signature of "from_result" incompatible with supertype "ResultBasedN" + main:32: error: Signature of "from_failure" incompatible with supertype "ResultBasedN" diff --git a/typesafety/test_interfaces/test_unwrappable/test_inheritance.yml b/typesafety/test_interfaces/test_unwrappable/test_inheritance.yml new file mode 100644 index 000000000..e5b346a78 --- /dev/null +++ b/typesafety/test_interfaces/test_unwrappable/test_inheritance.yml @@ -0,0 +1,73 @@ +- case: unwrappable_correct_inheritance + disable_cache: true + main: | + from returns.primitives.hkt import Kind2 + from returns.interfaces.unwrappable import Unwrappable + from typing import TypeVar + + T = TypeVar('T') + N = TypeVar('N') + + class MyOwn( + Kind2['MyOwn', T, N], + Unwrappable[T, N], + ): + def __init__(self, value: T, error: N) -> None: + ... + + def unwrap(self) -> T: + ... + + def failure(self) -> N: + ... + + x = MyOwn(1, 'a') + reveal_type(x.unwrap()) # N: Revealed type is 'builtins.int*' + reveal_type(x.failure()) # N: Revealed type is 'builtins.str*' + + +- case: unwrappable_missing_inheritance + disable_cache: true + main: | + from returns.primitives.hkt import Kind2 + from returns.interfaces.unwrappable import Unwrappable + from typing import TypeVar + + T = TypeVar('T') + N = TypeVar('N') + + class MyOwn( + Kind2['MyOwn', T, N], + Unwrappable[T, N], + ): + def __init__(self, value: T, error: N) -> None: + ... + + x = MyOwn(1, 'a') # E: Cannot instantiate abstract class 'MyOwn' with abstract attributes 'failure' and 'unwrap' + + +- case: unwrappable_wrong_inheritance + disable_cache: true + main: | + from returns.primitives.hkt import Kind2 + from returns.interfaces.unwrappable import Unwrappable + from typing import TypeVar + + T = TypeVar('T') + N = TypeVar('N') + + class MyOwn( + Kind2['MyOwn', T, N], + Unwrappable[T, N], + ): + def __init__(self, value: T, error: N) -> None: + ... + + def unwrap(self) -> int: + ... + + def failure(self) -> T: + ... + out: | + main:15: error: Return type "int" of "unwrap" incompatible with return type "T" in supertype "Unwrappable" + main:18: error: Return type "T" of "failure" incompatible with return type "N" in supertype "Unwrappable" diff --git a/typesafety/test_methods/test_apply.yml b/typesafety/test_methods/test_apply.yml new file mode 100644 index 000000000..a6dfe7eb8 --- /dev/null +++ b/typesafety/test_methods/test_apply.yml @@ -0,0 +1,154 @@ +- case: apply_wrong_extra_types + disable_cache: true + main: | + from returns.methods import apply + from returns.context import RequiresContextFutureResult + from typing import Callable + + test: RequiresContextFutureResult[Callable[[float], int], str, str] + x: RequiresContextFutureResult[float, float, float] + + apply(x, test) # E: Argument 2 to "internal_apply" has incompatible type "RequiresContextFutureResult[Callable[[float], int], str, str]"; expected "KindN[RequiresContextFutureResult[Any, Any, Any], Callable[[float], int], float, float]" + + +- case: apply_wrong_value_type + disable_cache: true + main: | + from returns.methods import apply + from returns.context import RequiresContextFutureResult + from typing import Callable + + test: RequiresContextFutureResult[Callable[[float], int], str, str] + x: RequiresContextFutureResult[str, str, str] + + apply(x, test) # E: Argument 2 to "internal_apply" has incompatible type "RequiresContextFutureResult[Callable[[float], int], str, str]"; expected "KindN[RequiresContextFutureResult[Any, Any, Any], Callable[[str], int], str, str]" + + +- case: apply_io + disable_cache: true + main: | + from returns.methods import apply + from returns.io import IO + + def test(arg: float) -> int: + ... + + x: IO[float] + reveal_type(apply(x, IO(test))) # N: Revealed type is 'returns.io.IO[builtins.int*]' + + +- case: apply_maybe + disable_cache: true + main: | + from returns.methods import apply + from returns.maybe import Maybe + + def test(arg: float) -> int: + ... + + x: Maybe[float] + reveal_type(apply(x, Maybe.from_value(test))) # N: Revealed type is 'returns.maybe.Maybe[builtins.int*]' + + +- case: apply_result + disable_cache: true + main: | + from returns.methods import apply + from returns.result import Result + from typing import Callable + + test: Result[Callable[[float], int], str] + x: Result[float, str] + + reveal_type(apply(x, test)) # N: Revealed type is 'returns.result.Result[builtins.int*, builtins.str]' + + +- case: apply_ioresult + disable_cache: true + main: | + from returns.methods import apply + from returns.io import IOResult + from typing import Callable + + test: IOResult[Callable[[float], int], str] + x: IOResult[float, str] + + reveal_type(apply(x, test)) # N: Revealed type is 'returns.io.IOResult[builtins.int*, builtins.str]' + + +- case: apply_requires_context + disable_cache: true + main: | + from returns.methods import apply + from returns.context import RequiresContext + from typing import Callable + + test: RequiresContext[Callable[[float], int], bool] + x: RequiresContext[float, bool] + + reveal_type(apply(x, test)) # N: Revealed type is 'returns.context.requires_context.RequiresContext[builtins.int*, builtins.bool]' + + +- case: apply_requires_context_result + disable_cache: true + main: | + from returns.methods import apply + from returns.context import RequiresContextResult + from typing import Callable + + test: RequiresContextResult[Callable[[float], int], str, bool] + x: RequiresContextResult[float, str, bool] + + reveal_type(apply(x, test)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.int*, builtins.str, builtins.bool]' + + +- case: apply_requires_context_ioresult + disable_cache: true + main: | + from returns.methods import apply + from returns.context import RequiresContextIOResult + from typing import Callable + + test: RequiresContextIOResult[Callable[[float], int], str, bool] + x: RequiresContextIOResult[float, str, bool] + + reveal_type(apply(x, test)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.int*, builtins.str, builtins.bool]' + + +- case: apply_requires_context_future_result + disable_cache: true + main: | + from returns.methods import apply + from returns.context import RequiresContextFutureResult + from typing import Callable + + test: RequiresContextFutureResult[Callable[[float], int], str, bool] + x: RequiresContextFutureResult[float, str, bool] + + reveal_type(apply(x, test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.int*, builtins.str, builtins.bool]' + + +- case: apply_future + disable_cache: true + main: | + from returns.methods import apply + from returns.future import Future + + def test(arg: float) -> int: + ... + + x: Future[float] + reveal_type(apply(x, Future.from_value(test))) # N: Revealed type is 'returns.future.Future[builtins.int*]' + + +- case: apply_futureresult + disable_cache: true + main: | + from returns.methods import apply + from returns.future import FutureResult + from typing import Callable + + test: FutureResult[Callable[[float], int], str] + x: FutureResult[float, str] + + reveal_type(apply(x, test)) # N: Revealed type is 'returns.future.FutureResult[builtins.int*, builtins.str]' diff --git a/typesafety/test_methods/test_bind.yml b/typesafety/test_methods/test_bind.yml new file mode 100644 index 000000000..0245163b6 --- /dev/null +++ b/typesafety/test_methods/test_bind.yml @@ -0,0 +1,208 @@ +- case: bind_variance + disable_cache: true + main: | + from returns.methods import bind + from returns.maybe import Maybe + + class A: ... + class B(A): ... + class C(B): ... + + def test(a: A) -> Maybe[C]: + ... + + x: Maybe[B] + reveal_type(bind(x, test)) # N: Revealed type is 'returns.maybe.Maybe[main.C*]' + + +- case: bind_wrong_error_type + disable_cache: true + main: | + from returns.methods import bind + from returns.result import Result + + def test(arg: float) -> Result[int, Exception]: + ... + + x: Result[float, str] + reveal_type(bind(x, test)) + out: | + main:8: error: Argument 2 to "internal_bind" has incompatible type "Callable[[float], Result[int, Exception]]"; expected "Callable[[float], KindN[Result[Any, Any], int, str, NoReturn]]" + main:8: note: Revealed type is 'returns.result.Result[builtins.int*, builtins.str]' + + +- case: bind_wrong_instance_type + disable_cache: true + main: | + from returns.methods import bind + from returns.result import Result + from returns.io import IOResult + + def test(arg: float) -> Result[int, str]: + ... + + x: IOResult[float, str] + reveal_type(bind(x, test)) + out: | + main:9: error: Argument 2 to "internal_bind" has incompatible type "Callable[[float], Result[int, str]]"; expected "Callable[[float], KindN[IOResult[Any, Any], int, str, NoReturn]]" + main:9: note: Revealed type is 'returns.io.IOResult[builtins.int*, builtins.str]' + + +- case: bind_io + disable_cache: true + main: | + from returns.methods import bind + from returns.io import IO + + def test(arg: float) -> IO[int]: + ... + + x: IO[float] + reveal_type(bind(x, test)) # N: Revealed type is 'returns.io.IO[builtins.int*]' + + +- case: bind_maybe + disable_cache: true + main: | + from returns.methods import bind + from returns.maybe import Maybe + + def test(arg: float) -> Maybe[int]: + ... + + x: Maybe[float] + reveal_type(bind(x, test)) # N: Revealed type is 'returns.maybe.Maybe[builtins.int*]' + + +- case: bind_result + disable_cache: true + main: | + from returns.methods import bind + from returns.result import Result + + def test(arg: float) -> Result[int, str]: + ... + + x: Result[float, str] + reveal_type(bind(x, test)) # N: Revealed type is 'returns.result.Result[builtins.int*, builtins.str]' + + +- case: bind_ioresult + disable_cache: true + main: | + from returns.methods import bind + from returns.io import IOResult + + def test(arg: float) -> IOResult[int, str]: + ... + + x: IOResult[float, str] + reveal_type(bind(x, test)) # N: Revealed type is 'returns.io.IOResult[builtins.int*, builtins.str]' + + +- case: bind_requires_context + disable_cache: true + main: | + from returns.methods import bind + from returns.context import RequiresContext + + def test(arg: float) -> RequiresContext[int, str]: + ... + + x: RequiresContext[float, str] + reveal_type(bind(x, test)) # N: Revealed type is 'returns.context.requires_context.RequiresContext[builtins.int*, builtins.str]' + + +- case: bind_requires_context_result + disable_cache: true + main: | + from returns.methods import bind + from returns.context import RequiresContextResult + + def test(arg: float) -> RequiresContextResult[int, bool, str]: + ... + + x: RequiresContextResult[float, bool, str] + reveal_type(bind(x, test)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.int*, builtins.bool, builtins.str]' + + +- case: bind_requires_context_ioresult + disable_cache: true + main: | + from returns.methods import bind + from returns.context import RequiresContextIOResult + + def test(arg: float) -> RequiresContextIOResult[int, bool, str]: + ... + + x: RequiresContextIOResult[float, bool, str] + reveal_type(bind(x, test)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.int*, builtins.bool, builtins.str]' + + +- case: bind_requires_context_future_result + disable_cache: true + main: | + from returns.methods import bind + from returns.context import RequiresContextFutureResult + + def test(arg: float) -> RequiresContextFutureResult[int, bool, str]: + ... + + x: RequiresContextFutureResult[float, bool, str] + reveal_type(bind(x, test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.int*, builtins.bool, builtins.str]' + + +- case: bind_future + disable_cache: true + main: | + from returns.methods import bind + from returns.future import Future + + def test(arg: float) -> Future[int]: + ... + + x: Future[float] + reveal_type(bind(x, test)) # N: Revealed type is 'returns.future.Future[builtins.int*]' + + +- case: bind_futureresult + disable_cache: true + main: | + from returns.methods import bind + from returns.future import FutureResult + + def test(arg: float) -> FutureResult[int, str]: + ... + + x: FutureResult[float, str] + reveal_type(bind(x, test)) # N: Revealed type is 'returns.future.FutureResult[builtins.int*, builtins.str]' + + +- case: bind_custom_type + disable_cache: true + main: | + from returns.methods import bind + from returns.primitives.hkt import Kind1, dekind + from returns.interfaces.bindable import Bindable1 + from typing import Callable, TypeVar + + T = TypeVar('T') + N = TypeVar('N') + + class MyOwn( + Kind1['MyOwn', T], + Bindable1[T], + ): + def __init__(self, value: T) -> None: + self.value = value + + def bind( + self, function: Callable[[T], Kind1['MyOwn', N]], + ) -> 'MyOwn[N]': + return dekind(function(self.value)) + + def test(arg: float) -> MyOwn[int]: + ... + + x: MyOwn[float] + reveal_type(bind(x, test)) # N: Revealed type is 'main.MyOwn[builtins.int*]' diff --git a/typesafety/test_methods/test_bind_result.yml b/typesafety/test_methods/test_bind_result.yml new file mode 100644 index 000000000..3f8f5dbaf --- /dev/null +++ b/typesafety/test_methods/test_bind_result.yml @@ -0,0 +1,144 @@ +- case: bind_result_wrong_first_type + disable_cache: true + main: | + from returns.methods import bind_result + from returns.context import RequiresContextFutureResult + from returns.result import Result + + def test(arg: float) -> Result[int, str]: + ... + + x: RequiresContextFutureResult[str, int, bool] + bind_result(x, test) # E: Argument 2 to "internal_bind_result" has incompatible type "Callable[[float], Result[int, str]]"; expected "Callable[[str], Result[int, int]]" + + +- case: bind_result_wrong_second_type + disable_cache: true + main: | + from returns.methods import bind_result + from returns.context import RequiresContextFutureResult + from returns.result import Result + + def test(arg: float) -> Result[int, str]: + ... + + x: RequiresContextFutureResult[float, int, bool] + bind_result(x, test) # E: Argument 2 to "internal_bind_result" has incompatible type "Callable[[float], Result[int, str]]"; expected "Callable[[float], Result[int, int]]" + + +- case: bind_result_ioresult + disable_cache: true + main: | + from returns.methods import bind_result + from returns.io import IOResult + from returns.result import Result + + def test(arg: float) -> Result[int, str]: + ... + + x: IOResult[float, str] + reveal_type(bind_result(x, test)) # N: Revealed type is 'returns.io.IOResult[builtins.int*, builtins.str]' + + +- case: bind_result_requires_context_result + disable_cache: true + main: | + from returns.methods import bind_result + from returns.context import RequiresContextResult + from returns.result import Result + + def test(arg: float) -> Result[int, str]: + ... + + x: RequiresContextResult[float, str, bool] + reveal_type(bind_result(x, test)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.int*, builtins.str, builtins.bool]' + + +- case: bind_result_requires_context_ioresult + disable_cache: true + main: | + from returns.methods import bind_result + from returns.context import RequiresContextIOResult + from returns.result import Result + + def test(arg: float) -> Result[int, str]: + ... + + x: RequiresContextIOResult[float, str, bool] + reveal_type(bind_result(x, test)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.int*, builtins.str, builtins.bool]' + + +- case: bind_result_requires_context_future_result + disable_cache: true + main: | + from returns.methods import bind_result + from returns.context import RequiresContextFutureResult + from returns.result import Result + + def test(arg: float) -> Result[int, str]: + ... + + x: RequiresContextFutureResult[float, str, bool] + reveal_type(bind_result(x, test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.int*, builtins.str, builtins.bool]' + + +- case: bind_result_futureresult + disable_cache: true + main: | + from returns.methods import bind_result + from returns.future import FutureResult + from returns.result import Result + + def test(arg: float) -> Result[int, str]: + ... + + x: FutureResult[float, str] + reveal_type(bind_result(x, test)) # N: Revealed type is 'returns.future.FutureResult[builtins.int*, builtins.str]' + + +- case: bind_result_custom_type + disable_cache: true + main: | + from typing import Callable, TypeVar, Any + from returns.interfaces.specific.result import ResultBased2 + from returns.primitives.hkt import Kind2 + from returns.result import Result + from returns.methods import bind_result + + _ValueType = TypeVar('_ValueType') + _NewValueType = TypeVar('_NewValueType') + + # Result related: + _ErrorType = TypeVar('_ErrorType') + _NewErrorType = TypeVar('_NewErrorType') + + class MyClass( + Kind2['MyClass', _ValueType, _ErrorType], + ResultBased2[_ValueType, _ErrorType], + ): + def bind_result( + self, + function: Callable[ + [_ValueType], + Result[_NewValueType, _ErrorType], + ], + ) -> MyClass[_NewValueType, _ErrorType]: + ... + + @classmethod + def from_result( + self, inner_value: Result[_NewValueType, _NewErrorType], + ) -> MyClass[_NewValueType, _NewErrorType]: + ... + + @classmethod + def from_failure( + cls, inner_value: _NewErrorType, + ) -> MyClass[Any, _NewErrorType]: + ... + + def test(a: int) -> Result[float, str]: + ... + + x: MyClass[int, str] + reveal_type(bind_result(x, test)) # N: Revealed type is 'main.MyClass[builtins.float*, builtins.str]' diff --git a/typesafety/test_methods/test_map.yml b/typesafety/test_methods/test_map.yml new file mode 100644 index 000000000..f324a305e --- /dev/null +++ b/typesafety/test_methods/test_map.yml @@ -0,0 +1,192 @@ +- case: map_variance + disable_cache: true + main: | + from returns.methods import map_ + from returns.maybe import Maybe + + class A: ... + class B(A): ... + class C(B): ... + + def test(a: A) -> C: + ... + + x: Maybe[B] + reveal_type(map_(x, test)) # N: Revealed type is 'returns.maybe.Maybe[main.C*]' + + +- case: map_wrong_value_type + disable_cache: true + main: | + from returns.methods import map_ + from returns.result import Result + from returns.io import IOResult + + def test(arg: float) -> int: + ... + + x: IOResult[str, str] + reveal_type(map_(x, test)) + out: | + main:9: error: Argument 2 to "internal_map" has incompatible type "Callable[[float], int]"; expected "Callable[[str], int]" + main:9: note: Revealed type is 'returns.io.IOResult[builtins.int*, builtins.str]' + + +- case: map_io + disable_cache: true + main: | + from returns.methods import map_ + from returns.io import IO + + def test(arg: float) -> int: + ... + + x: IO[float] + reveal_type(map_(x, test)) # N: Revealed type is 'returns.io.IO[builtins.int*]' + + +- case: map_maybe + disable_cache: true + main: | + from returns.methods import map_ + from returns.maybe import Maybe + + def test(arg: float) -> int: + ... + + x: Maybe[float] + reveal_type(map_(x, test)) # N: Revealed type is 'returns.maybe.Maybe[builtins.int*]' + + +- case: map_result + disable_cache: true + main: | + from returns.methods import map_ + from returns.result import Result + + def test(arg: float) -> int: + ... + + x: Result[float, str] + reveal_type(map_(x, test)) # N: Revealed type is 'returns.result.Result[builtins.int*, builtins.str]' + + +- case: map_ioresult + disable_cache: true + main: | + from returns.methods import map_ + from returns.io import IOResult + + def test(arg: float) -> int: + ... + + x: IOResult[float, str] + reveal_type(map_(x, test)) # N: Revealed type is 'returns.io.IOResult[builtins.int*, builtins.str]' + + +- case: map_requires_context + disable_cache: true + main: | + from returns.methods import map_ + from returns.context import RequiresContext + + def test(arg: float) -> int: + ... + + x: RequiresContext[float, str] + reveal_type(map_(x, test)) # N: Revealed type is 'returns.context.requires_context.RequiresContext[builtins.int*, builtins.str]' + + +- case: map_requires_context_result + disable_cache: true + main: | + from returns.methods import map_ + from returns.context import RequiresContextResult + + def test(arg: float) -> int: + ... + + x: RequiresContextResult[float, bool, str] + reveal_type(map_(x, test)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.int*, builtins.bool, builtins.str]' + + +- case: map_requires_context_ioresult + disable_cache: true + main: | + from returns.methods import map_ + from returns.context import RequiresContextIOResult + + def test(arg: float) -> int: + ... + + x: RequiresContextIOResult[float, bool, str] + reveal_type(map_(x, test)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.int*, builtins.bool, builtins.str]' + + +- case: map_requires_context_future_result + disable_cache: true + main: | + from returns.methods import map_ + from returns.context import RequiresContextFutureResult + + def test(arg: float) -> int: + ... + + x: RequiresContextFutureResult[float, bool, str] + reveal_type(map_(x, test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.int*, builtins.bool, builtins.str]' + + +- case: map_future + disable_cache: true + main: | + from returns.methods import map_ + from returns.future import Future + + def test(arg: float) -> int: + ... + + x: Future[float] + reveal_type(map_(x, test)) # N: Revealed type is 'returns.future.Future[builtins.int*]' + + +- case: map_futureresult + disable_cache: true + main: | + from returns.methods import map_ + from returns.future import FutureResult + + def test(arg: float) -> int: + ... + + x: FutureResult[float, str] + reveal_type(map_(x, test)) # N: Revealed type is 'returns.future.FutureResult[builtins.int*, builtins.str]' + + +- case: map_custom_type + disable_cache: true + main: | + from returns.methods import map_ + from returns.primitives.hkt import Kind1, dekind + from returns.interfaces.mappable import Mappable1 + from typing import Callable, TypeVar + + T = TypeVar('T') + N = TypeVar('N') + + class MyOwn( + Kind1['MyOwn', T], + Mappable1[T], + ): + def __init__(self, value: T) -> None: + self.value = value + + def map( + self, function: Callable[[T], N], + ) -> 'MyOwn[N]': + return MyOwn(function(self.value)) + + def test(arg: float) -> int: + ... + + x: MyOwn[float] + reveal_type(map_(x, test)) # N: Revealed type is 'main.MyOwn[builtins.int*]' diff --git a/typesafety/test_methods/test_rescue.yml b/typesafety/test_methods/test_rescue.yml new file mode 100644 index 000000000..d9d3cd496 --- /dev/null +++ b/typesafety/test_methods/test_rescue.yml @@ -0,0 +1,102 @@ +- case: rescue_wrong_second_type + disable_cache: true + main: | + from returns.methods import rescue + from returns.context import RequiresContextIOResult + + def test(arg: float) -> RequiresContextIOResult[float, str, int]: + ... + + x: RequiresContextIOResult[float, str, int] + rescue(x, test) # E: Argument 2 to "internal_rescue" has incompatible type "Callable[[float], RequiresContextIOResult[float, str, int]]"; expected "Callable[[str], KindN[RequiresContextIOResult[Any, Any, Any], float, str, int]]" + + +- case: rescue_wrong_else_types + disable_cache: true + main: | + from returns.methods import rescue + from returns.context import RequiresContextIOResult + + def test(arg: float) -> RequiresContextIOResult[float, str, int]: + ... + + x: RequiresContextIOResult[str, float, str] + rescue(x, test) # E: Argument 2 to "internal_rescue" has incompatible type "Callable[[float], RequiresContextIOResult[float, str, int]]"; expected "Callable[[float], KindN[RequiresContextIOResult[Any, Any, Any], str, str, str]]" + + +- case: rescue_result + disable_cache: true + main: | + from returns.methods import rescue + from returns.result import Result + + def test(arg: float) -> Result[int, str]: + ... + + x: Result[int, float] + reveal_type(rescue(x, test)) # N: Revealed type is 'returns.result.Result[builtins.int, builtins.str*]' + + +- case: rescue_ioresult + disable_cache: true + main: | + from returns.methods import rescue + from returns.io import IOResult + + def test(arg: float) -> IOResult[int, str]: + ... + + x: IOResult[int, float] + reveal_type(rescue(x, test)) # N: Revealed type is 'returns.io.IOResult[builtins.int, builtins.str*]' + + +- case: rescue_context_result + disable_cache: true + main: | + from returns.methods import rescue + from returns.context import RequiresContextResult + + def test(arg: float) -> RequiresContextResult[float, str, int]: + ... + + x: RequiresContextResult[float, float, int] + reveal_type(rescue(x, test)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.float, builtins.str*, builtins.int]' + + +- case: rescue_context_ioresult + disable_cache: true + main: | + from returns.methods import rescue + from returns.context import RequiresContextIOResult + + def test(arg: float) -> RequiresContextIOResult[float, str, int]: + ... + + x: RequiresContextIOResult[float, float, int] + reveal_type(rescue(x, test)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.float, builtins.str*, builtins.int]' + + +- case: rescue_context_future_result + disable_cache: true + main: | + from returns.methods import rescue + from returns.context import RequiresContextFutureResult + + def test(arg: float) -> RequiresContextFutureResult[float, str, int]: + ... + + x: RequiresContextFutureResult[float, float, int] + reveal_type(rescue(x, test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.float, builtins.str*, builtins.int]' + + +- case: rescue_future_result + disable_cache: true + main: | + from returns.methods import rescue + from returns.future import FutureResult + + def test(arg: float) -> FutureResult[int, str]: + ... + + x: FutureResult[int, float] + reveal_type(rescue(x, test)) # N: Revealed type is 'returns.future.FutureResult[builtins.int, builtins.str*]' diff --git a/typesafety/test_pipeline/test_flow/test_flow_args.yml b/typesafety/test_pipeline/test_flow/test_flow_args.yml index 60b7e5f9b..a1301370b 100644 --- a/typesafety/test_pipeline/test_flow/test_flow_args.yml +++ b/typesafety/test_pipeline/test_flow/test_flow_args.yml @@ -48,14 +48,5 @@ identity, identity, identity, - identity, - identity, - identity, - identity, - identity, - identity, - identity, - identity, - identity, # very long amount of args! ) ) diff --git a/typesafety/test_pipeline/test_flow/test_flow_base.yml b/typesafety/test_pipeline/test_flow/test_flow_base.yml index 52c66fd5a..19ef8b7bb 100644 --- a/typesafety/test_pipeline/test_flow/test_flow_base.yml +++ b/typesafety/test_pipeline/test_flow/test_flow_base.yml @@ -129,4 +129,42 @@ def mappable(arg: float) -> bool: ... - reveal_type(flow(x, bind(bound), identity, map_(mappable))) # N: Revealed type is 'returns.result.Result[builtins.bool, builtins.str*]' + reveal_type(flow(x, bind(bound), identity, map_(mappable))) # N: Revealed type is 'returns.result.Result*[builtins.bool, builtins.str*]' + + +- case: bind_result_and_flow1 + disable_cache: true + main: | + from returns.result import Result + from returns.io import IOResult + from returns.functions import identity + from returns.pointfree import bind_result + from returns.pipeline import flow + + def test(arg: int) -> Result[float, str]: + ... + + def second(arg: float) -> Result[bool, str]: + ... + + r: IOResult[int, str] + reveal_type(flow(r, bind_result(test), bind_result(second), identity)) # N: Revealed type is 'returns.io.IOResult*[builtins.bool, builtins.str]' + + +- case: bind_result_and_flow2 + disable_cache: true + main: | + from returns.result import Result + from returns.io import IOResult + from returns.functions import identity + from returns.pointfree import bind_result + from returns.pipeline import flow + + def test(arg: int) -> Result[float, str]: + ... + + def second(arg: float) -> Result[bool, str]: + ... + + r: IOResult[int, str] + reveal_type(flow(r, bind_result(test), bind_result(second))) # N: Revealed type is 'returns.io.IOResult*[builtins.bool, builtins.str]' diff --git a/typesafety/test_pipeline/test_flow/test_flow_curry.yml b/typesafety/test_pipeline/test_flow/test_flow_curry.yml index 6af87ab03..112100f88 100644 --- a/typesafety/test_pipeline/test_flow/test_flow_curry.yml +++ b/typesafety/test_pipeline/test_flow/test_flow_curry.yml @@ -6,11 +6,10 @@ from returns.functions import identity @curry - def curried(a: int, b: int, c: str) -> float: + def curried(a: int, b: int) -> float: ... - reveal_type(flow(1, curried, identity)(2)('a')) # N: Revealed type is 'builtins.float' - reveal_type(flow(1, curried, identity)(2, 'a')) # N: Revealed type is 'builtins.float' + reveal_type(flow(1, curried)(1)) # N: Revealed type is 'builtins.float' - case: flow_function_with_curried2 diff --git a/typesafety/test_pipeline/test_is_successful.yml b/typesafety/test_pipeline/test_is_successful.yml index 66ff53ba0..9c499d86e 100644 --- a/typesafety/test_pipeline/test_is_successful.yml +++ b/typesafety/test_pipeline/test_is_successful.yml @@ -29,3 +29,39 @@ from returns.maybe import Maybe reveal_type(is_successful(Maybe.from_value(1))) # N: Revealed type is 'builtins.bool' + + +- case: custom_type_is_successful + disable_cache: true + main: | + from returns.pipeline import is_successful + from returns.primitives.hkt import Kind2 + from returns.primitives.exceptions import UnwrapFailedError + from returns.interfaces.unwrappable import Unwrappable + from typing import TypeVar + + T = TypeVar('T') + N = TypeVar('N') + + class MyOwn( + Kind2['MyOwn', T, N], + Unwrappable[T, N], + ): + def __init__(self, value: T, error: N) -> None: + self.value = value + self.error = error + + def unwrap(self) -> T: + if self.error: + raise UnwrapFailedError(self) + return self.value + + def failure(self) -> N: + if self.value: + raise UnwrapFailedError(self) + return self.error + + x: MyOwn[int, str] + reveal_type(x.unwrap()) # N: Revealed type is 'builtins.int*' + reveal_type(x.failure()) # N: Revealed type is 'builtins.str*' + reveal_type(is_successful(x)) # N: Revealed type is 'builtins.bool' diff --git a/typesafety/test_pipeline/test_managed/test_managed_reader_future_result.yml b/typesafety/test_pipeline/test_managed/test_managed_reader_future_result.yml index 26016791b..92e13fc91 100644 --- a/typesafety/test_pipeline/test_managed/test_managed_reader_future_result.yml +++ b/typesafety/test_pipeline/test_managed/test_managed_reader_future_result.yml @@ -5,16 +5,16 @@ from returns.pipeline import managed from returns.result import Result - def use(acquired_value: int) -> ReaderFutureResult[bool, float, str]: + def use(acquired_value: int) -> ReaderFutureResult[float, str, bool]: ... def release( acquired_value: int, use_value: Result[float, str], - ) -> ReaderFutureResult[bool, None, str]: + ) -> ReaderFutureResult[None, str, bool]: ... - reveal_type(managed(use, release)) # N: Revealed type is 'def (returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.int*, builtins.str*]) -> returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.float*, builtins.str*]' + reveal_type(managed(use, release)) # N: Revealed type is 'def (returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.int*, builtins.str*, builtins.bool*]) -> returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.float*, builtins.str*, builtins.bool*]' - case: managed_with_reader_future_result_error @@ -24,17 +24,17 @@ from returns.pipeline import managed from returns.result import Result - def use(acquired_value: int) -> ReaderFutureResult[bool, float, str]: + def use(acquired_value: int) -> ReaderFutureResult[float, str, bool]: ... def release( acquired_value: int, use_value: Result[float, int], - ) -> ReaderFutureResult[str, int, str]: + ) -> ReaderFutureResult[int, str, str]: ... reveal_type(managed(use, release)) # TODO: this type is really strange! out: | - main:14: error: Argument 1 to "_managed" has incompatible type "Callable[[int], RequiresContextFutureResult[bool, float, str]]"; expected "Callable[[int], IOResult[float, int]]" - main:14: error: Argument 2 to "_managed" has incompatible type "Callable[[int, Result[float, int]], RequiresContextFutureResult[str, int, str]]"; expected "Callable[[int, Result[float, int]], IOResult[None, int]]" + main:14: error: Argument 1 to "_managed" has incompatible type "Callable[[int], RequiresContextFutureResult[float, str, bool]]"; expected "Callable[[int], IOResult[float, int]]" + main:14: error: Argument 2 to "_managed" has incompatible type "Callable[[int, Result[float, int]], RequiresContextFutureResult[int, str, str]]"; expected "Callable[[int, Result[float, int]], IOResult[None, int]]" main:14: note: Revealed type is 'def (returns.io.IOResult[builtins.int*, builtins.int*]) -> returns.io.IOResult[builtins.float*, builtins.int*]' diff --git a/typesafety/test_pipeline/test_managed/test_managed_reader_ioresult.yml b/typesafety/test_pipeline/test_managed/test_managed_reader_ioresult.yml index 912c00511..35169ca2d 100644 --- a/typesafety/test_pipeline/test_managed/test_managed_reader_ioresult.yml +++ b/typesafety/test_pipeline/test_managed/test_managed_reader_ioresult.yml @@ -5,16 +5,16 @@ from returns.pipeline import managed from returns.result import Result - def use(acquired_value: int) -> ReaderIOResult[bool, float, str]: + def use(acquired_value: int) -> ReaderIOResult[float, str, bool]: ... def release( acquired_value: int, use_value: Result[float, str], - ) -> ReaderIOResult[bool, None, str]: + ) -> ReaderIOResult[None, str, bool]: ... - reveal_type(managed(use, release)) # N: Revealed type is 'def (returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.bool, builtins.int, builtins.str]) -> returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.bool, builtins.float, builtins.str]' + reveal_type(managed(use, release)) # N: Revealed type is 'def (returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.int*, builtins.str*, builtins.bool*]) -> returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.float*, builtins.str*, builtins.bool*]' - case: managed_with_reader_ioresult_error @@ -24,17 +24,17 @@ from returns.pipeline import managed from returns.result import Result - def use(acquired_value: int) -> ReaderIOResult[bool, float, str]: + def use(acquired_value: int) -> ReaderIOResult[float, str, bool]: ... def release( acquired_value: int, use_value: Result[float, int], - ) -> ReaderIOResult[str, int, str]: + ) -> ReaderIOResult[int, str, str]: ... reveal_type(managed(use, release)) # TODO: this type is really strange! out: | - main:14: error: Argument 1 to "_managed" has incompatible type "Callable[[int], RequiresContextIOResult[bool, float, str]]"; expected "Callable[[int], IOResult[float, int]]" - main:14: error: Argument 2 to "_managed" has incompatible type "Callable[[int, Result[float, int]], RequiresContextIOResult[str, int, str]]"; expected "Callable[[int, Result[float, int]], IOResult[None, int]]" + main:14: error: Argument 1 to "_managed" has incompatible type "Callable[[int], RequiresContextIOResult[float, str, bool]]"; expected "Callable[[int], IOResult[float, int]]" + main:14: error: Argument 2 to "_managed" has incompatible type "Callable[[int, Result[float, int]], RequiresContextIOResult[int, str, str]]"; expected "Callable[[int, Result[float, int]], IOResult[None, int]]" main:14: note: Revealed type is 'def (returns.io.IOResult[builtins.int*, builtins.int*]) -> returns.io.IOResult[builtins.float*, builtins.int*]' diff --git a/typesafety/test_pipeline/test_pipe/test_pipe_base.yml b/typesafety/test_pipeline/test_pipe/test_pipe_base.yml index f3870d31e..ddc155a41 100644 --- a/typesafety/test_pipeline/test_pipe/test_pipe_base.yml +++ b/typesafety/test_pipeline/test_pipe/test_pipe_base.yml @@ -166,4 +166,4 @@ def mappable(arg: float) -> bool: ... - reveal_type(pipe(bind(bound), identity, map_(mappable))(x)) # N: Revealed type is 'returns.result.Result[builtins.bool, builtins.str*]' + reveal_type(pipe(bind(bound), identity, map_(mappable))(x)) # N: Revealed type is 'returns.result.Result*[builtins.bool, builtins.str*]' diff --git a/typesafety/test_pointfree/test_alt.yml b/typesafety/test_pointfree/test_alt.yml deleted file mode 100644 index 3cc68c108..000000000 --- a/typesafety/test_pointfree/test_alt.yml +++ /dev/null @@ -1,139 +0,0 @@ -- case: alt_variance - disable_cache: true - main: | - from returns.pointfree import alt - from returns.result import Result - - class A: ... - class B(A): ... - class C(B): ... - - x: Result[str, B] - - def test(a: A) -> C: - ... - - reveal_type(alt(test)(x)) # N: Revealed type is 'returns.result.Result[builtins.str*, main.C]' - - -- case: alt_callback_protocol - disable_cache: true - main: | - from typing import Callable, TypeVar - from returns.pointfree import alt - from returns.result import Result - - _ValueType = TypeVar('_ValueType', contravariant=True) - _ErrorType = TypeVar('_ErrorType', contravariant=True) - _NewErrorType = TypeVar('_NewErrorType', covariant=True) - - def ensure_callback( - f: Callable[ - [Result[_ValueType, _ErrorType]], - Result[_ValueType, _NewErrorType], - ], - c: Result[_ValueType, _ErrorType], - ) -> Result[_ValueType, _NewErrorType]: - return f(c) - - def test(arg: int) -> float: - return arg + 1.5 - - x: Result[str, int] - reveal_type(ensure_callback(alt(test), x)) # N: Revealed type is 'returns.result.Result[builtins.str, builtins.float*]' - - -- case: alt_and_flow - disable_cache: true - main: | - from returns.result import Result - from returns.functions import identity - from returns.pointfree import alt - from returns.pipeline import flow - - def test(arg: int) -> float: - ... - - def stringify(arg: float) -> str: - ... - - r: Result[bool, int] - reveal_type(flow(r, alt(test), alt(stringify), identity)) # N: Revealed type is 'returns.result.Result*[builtins.bool*, builtins.str]' - - -- case: alt_result - disable_cache: true - main: | - from returns.pointfree import alt - from returns.result import Result - - def test(arg: float) -> int: - ... - - x: Result[str, float] - reveal_type(alt(test)(x)) # N: Revealed type is 'returns.result.Result[builtins.str*, builtins.int]' - - -- case: alt_ioresult - disable_cache: true - main: | - from returns.pointfree import alt - from returns.io import IOResult - - def test(arg: float) -> int: - ... - - x: IOResult[str, float] - reveal_type(alt(test)(x)) # N: Revealed type is 'returns.io.IOResult[builtins.str*, builtins.int]' - - -- case: alt_requires_context_result - disable_cache: true - main: | - from returns.pointfree import alt - from returns.context import RequiresContextResult - - def test(arg: float) -> int: - ... - - x: RequiresContextResult[bool, str, float] - reveal_type(alt(test)(x)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.bool*, builtins.str*, builtins.int]' - - -- case: alt_requires_context_ioresult - disable_cache: true - main: | - from returns.pointfree import alt - from returns.context import RequiresContextIOResult - - def test(arg: float) -> int: - ... - - x: RequiresContextIOResult[bool, str, float] - reveal_type(alt(test)(x)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.bool*, builtins.str*, builtins.int]' - - -- case: alt_requires_context_future_result - disable_cache: true - main: | - from returns.pointfree import alt - from returns.context import RequiresContextFutureResult - - def test(arg: float) -> int: - ... - - x: RequiresContextFutureResult[bool, str, float] - reveal_type(alt(test)(x)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.str*, builtins.int]' - - -- case: alt_futureresult - disable_cache: true - main: | - from returns.pointfree import alt - from returns.future import FutureResult - - def test(arg: float) -> int: - ... - - x: FutureResult[str, float] - reveal_type(alt(test)(x)) # N: Revealed type is 'returns.future.FutureResult[builtins.str*, builtins.int]' diff --git a/typesafety/test_pointfree/test_apply.yml b/typesafety/test_pointfree/test_apply.yml index 36eb43912..24e1b870c 100644 --- a/typesafety/test_pointfree/test_apply.yml +++ b/typesafety/test_pointfree/test_apply.yml @@ -12,6 +12,32 @@ reveal_type(flow(test, x.apply)) # N: Revealed type is 'returns.result.Result[builtins.int*, builtins.str]' +- case: apply_wrong_extra_types + disable_cache: true + main: | + from returns.pointfree import apply + from returns.context import RequiresContextFutureResult + from typing import Callable + + test: RequiresContextFutureResult[Callable[[float], int], str, str] + x: RequiresContextFutureResult[float, float, float] + + apply(test)(x) # E: Argument 1 has incompatible type "RequiresContextFutureResult[float, float, float]"; expected "KindN[RequiresContextFutureResult[Any, Any, Any], float, str, str]" + + +- case: apply_wrong_value_type + disable_cache: true + main: | + from returns.pointfree import apply + from returns.context import RequiresContextFutureResult + from typing import Callable + + test: RequiresContextFutureResult[Callable[[float], int], str, str] + x: RequiresContextFutureResult[str, str, str] + + apply(test)(x) # E: Argument 1 has incompatible type "RequiresContextFutureResult[str, str, str]"; expected "KindN[RequiresContextFutureResult[Any, Any, Any], float, str, str]" + + - case: apply_io disable_cache: true main: | @@ -21,7 +47,8 @@ def test(arg: float) -> int: ... - reveal_type(apply(IO(test))) # N: Revealed type is 'def (returns.io.IO[builtins.float*]) -> returns.io.IO[builtins.int*]' + x: IO[float] + reveal_type(apply(IO(test))(x)) # N: Revealed type is 'returns.io.IO*[builtins.int*]' - case: apply_maybe @@ -33,7 +60,8 @@ def test(arg: float) -> int: ... - reveal_type(apply(Maybe.from_value(test))) # N: Revealed type is 'def (returns.maybe.Maybe[builtins.float*]) -> returns.maybe.Maybe[builtins.int*]' + x: Maybe[float] + reveal_type(apply(Maybe.from_value(test))(x)) # N: Revealed type is 'returns.maybe.Maybe*[builtins.int*]' - case: apply_result @@ -44,8 +72,9 @@ from typing import Callable test: Result[Callable[[float], int], str] + x: Result[float, str] - reveal_type(apply(test)) # N: Revealed type is 'def (returns.result.Result[builtins.float*, builtins.str*]) -> returns.result.Result[builtins.int*, builtins.str*]' + reveal_type(apply(test)(x)) # N: Revealed type is 'returns.result.Result*[builtins.int*, builtins.str*]' - case: apply_ioresult @@ -56,8 +85,9 @@ from typing import Callable test: IOResult[Callable[[float], int], str] + x: IOResult[float, str] - reveal_type(apply(test)) # N: Revealed type is 'def (returns.io.IOResult[builtins.float*, builtins.str*]) -> returns.io.IOResult[builtins.int*, builtins.str*]' + reveal_type(apply(test)(x)) # N: Revealed type is 'returns.io.IOResult*[builtins.int*, builtins.str*]' - case: apply_requires_context @@ -67,9 +97,10 @@ from returns.context import RequiresContext from typing import Callable - test: RequiresContext[bool, Callable[[float], int]] + test: RequiresContext[Callable[[float], int], bool] + x: RequiresContext[float, bool] - reveal_type(apply(test)) # N: Revealed type is 'def (returns.context.requires_context.RequiresContext[builtins.bool*, builtins.float*]) -> returns.context.requires_context.RequiresContext[builtins.bool*, builtins.int*]' + reveal_type(apply(test)(x)) # N: Revealed type is 'returns.context.requires_context.RequiresContext*[builtins.int*, builtins.bool*]' - case: apply_requires_context_result @@ -79,9 +110,10 @@ from returns.context import RequiresContextResult from typing import Callable - test: RequiresContextResult[bool, Callable[[float], int], str] + test: RequiresContextResult[Callable[[float], int], str, bool] + x: RequiresContextResult[float, str, bool] - reveal_type(apply(test)) # N: Revealed type is 'def (returns.context.requires_context_result.RequiresContextResult[builtins.bool*, builtins.float*, builtins.str*]) -> returns.context.requires_context_result.RequiresContextResult[builtins.bool*, builtins.int*, builtins.str*]' + reveal_type(apply(test)(x)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult*[builtins.int*, builtins.str*, builtins.bool*]' - case: apply_requires_context_ioresult @@ -91,9 +123,10 @@ from returns.context import RequiresContextIOResult from typing import Callable - test: RequiresContextIOResult[bool, Callable[[float], int], str] + test: RequiresContextIOResult[Callable[[float], int], str, bool] + x: RequiresContextIOResult[float, str, bool] - reveal_type(apply(test)) # N: Revealed type is 'def (returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.bool*, builtins.float*, builtins.str*]) -> returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.bool*, builtins.int*, builtins.str*]' + reveal_type(apply(test)(x)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult*[builtins.int*, builtins.str*, builtins.bool*]' - case: apply_requires_context_future_result @@ -103,9 +136,10 @@ from returns.context import RequiresContextFutureResult from typing import Callable - test: RequiresContextFutureResult[bool, Callable[[float], int], str] + test: RequiresContextFutureResult[Callable[[float], int], str, bool] + x: RequiresContextFutureResult[float, str, bool] - reveal_type(apply(test)) # N: Revealed type is 'def (returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.float*, builtins.str*]) -> returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.int*, builtins.str*]' + reveal_type(apply(test)(x)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult*[builtins.int*, builtins.str*, builtins.bool*]' - case: apply_future @@ -117,7 +151,8 @@ def test(arg: float) -> int: ... - reveal_type(apply(Future.from_value(test))) # N: Revealed type is 'def (returns.future.Future[builtins.float*]) -> returns.future.Future[builtins.int*]' + x: Future[float] + reveal_type(apply(Future.from_value(test))(x)) # N: Revealed type is 'returns.future.Future*[builtins.int*]' - case: apply_futureresult @@ -128,5 +163,6 @@ from typing import Callable test: FutureResult[Callable[[float], int], str] + x: FutureResult[float, str] - reveal_type(apply(test)) # N: Revealed type is 'def (returns.future.FutureResult[builtins.float*, builtins.str*]) -> returns.future.FutureResult[builtins.int*, builtins.str*]' + reveal_type(apply(test)(x)) # N: Revealed type is 'returns.future.FutureResult*[builtins.int*, builtins.str*]' diff --git a/typesafety/test_pointfree/test_bind.yml b/typesafety/test_pointfree/test_bind.yml index c6696eb9a..f6f08db5a 100644 --- a/typesafety/test_pointfree/test_bind.yml +++ b/typesafety/test_pointfree/test_bind.yml @@ -8,12 +8,11 @@ class B(A): ... class C(B): ... - x: Maybe[B] - def test(a: A) -> Maybe[C]: ... - reveal_type(bind(test)(x)) # N: Revealed type is 'returns.maybe.Maybe[main.C*]' + x: Maybe[B] + reveal_type(bind(test)(x)) # N: Revealed type is 'returns.maybe.Maybe*[main.C*]' - case: bind_wrong_error_type @@ -28,8 +27,22 @@ x: Result[float, str] reveal_type(bind(test)(x)) out: | - main:8: error: Argument 1 has incompatible type "Result[float, str]"; expected "Result[float, Exception]" - main:8: note: Revealed type is 'returns.result.Result[builtins.int*, builtins.Exception*]' + main:8: error: Argument 1 has incompatible type "Result[float, str]"; expected "KindN[Result[Any, Any], float, Exception, NoReturn]" + main:8: note: Revealed type is 'returns.result.Result*[builtins.int*, builtins.Exception*]' + + +- case: bind_with_flow + disable_cache: true + main: | + from returns.pointfree import bind + from returns.pipeline import flow + from returns.result import Result + + def test(arg: float) -> Result[int, str]: + ... + + x: Result[float, str] + reveal_type(flow(x, bind(test))) # N: Revealed type is 'returns.result.Result[builtins.int, builtins.str]' - case: bind_io @@ -41,7 +54,8 @@ def test(arg: float) -> IO[int]: ... - reveal_type(bind(test)) # N: Revealed type is 'def (returns.io.IO[builtins.float*]) -> returns.io.IO[builtins.int*]' + x: IO[float] + reveal_type(bind(test)(x)) # N: Revealed type is 'returns.io.IO*[builtins.int*]' - case: bind_maybe @@ -53,7 +67,8 @@ def test(arg: float) -> Maybe[int]: ... - reveal_type(bind(test)) # N: Revealed type is 'def (returns.maybe.Maybe[builtins.float*]) -> returns.maybe.Maybe[builtins.int*]' + x: Maybe[float] + reveal_type(bind(test)(x)) # N: Revealed type is 'returns.maybe.Maybe*[builtins.int*]' - case: bind_result @@ -65,7 +80,8 @@ def test(arg: float) -> Result[int, str]: ... - reveal_type(bind(test)) # N: Revealed type is 'def (returns.result.Result[builtins.float*, builtins.str*]) -> returns.result.Result[builtins.int*, builtins.str*]' + x: Result[float, str] + reveal_type(bind(test)(x)) # N: Revealed type is 'returns.result.Result*[builtins.int*, builtins.str*]' - case: bind_ioresult @@ -77,7 +93,8 @@ def test(arg: float) -> IOResult[int, str]: ... - reveal_type(bind(test)) # N: Revealed type is 'def (returns.io.IOResult[builtins.float*, builtins.str*]) -> returns.io.IOResult[builtins.int*, builtins.str*]' + x: IOResult[float, str] + reveal_type(bind(test)(x)) # N: Revealed type is 'returns.io.IOResult*[builtins.int*, builtins.str*]' - case: bind_requires_context @@ -89,7 +106,8 @@ def test(arg: float) -> RequiresContext[int, str]: ... - reveal_type(bind(test)) # N: Revealed type is 'def (returns.context.requires_context.RequiresContext[builtins.int*, builtins.float*]) -> returns.context.requires_context.RequiresContext[builtins.int*, builtins.str*]' + x: RequiresContext[float, str] + reveal_type(bind(test)(x)) # N: Revealed type is 'returns.context.requires_context.RequiresContext*[builtins.int*, builtins.str*]' - case: bind_requires_context_result @@ -98,10 +116,11 @@ from returns.pointfree import bind from returns.context import RequiresContextResult - def test(arg: float) -> RequiresContextResult[bool, int, str]: + def test(arg: float) -> RequiresContextResult[int, bool, str]: ... - reveal_type(bind(test)) # N: Revealed type is 'def (returns.context.requires_context_result.RequiresContextResult[builtins.bool*, builtins.float*, builtins.str*]) -> returns.context.requires_context_result.RequiresContextResult[builtins.bool*, builtins.int*, builtins.str*]' + x: RequiresContextResult[float, bool, str] + reveal_type(bind(test)(x)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult*[builtins.int*, builtins.bool*, builtins.str*]' - case: bind_requires_context_ioresult @@ -110,10 +129,11 @@ from returns.pointfree import bind from returns.context import RequiresContextIOResult - def test(arg: float) -> RequiresContextIOResult[bool, int, str]: + def test(arg: float) -> RequiresContextIOResult[int, bool, str]: ... - reveal_type(bind(test)) # N: Revealed type is 'def (returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.bool*, builtins.float*, builtins.str*]) -> returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.bool*, builtins.int*, builtins.str*]' + x: RequiresContextIOResult[float, bool, str] + reveal_type(bind(test)(x)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult*[builtins.int*, builtins.bool*, builtins.str*]' - case: bind_requires_context_future_result @@ -122,10 +142,11 @@ from returns.pointfree import bind from returns.context import RequiresContextFutureResult - def test(arg: float) -> RequiresContextFutureResult[bool, int, str]: + def test(arg: float) -> RequiresContextFutureResult[int, bool, str]: ... - reveal_type(bind(test)) # N: Revealed type is 'def (returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.float*, builtins.str*]) -> returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.int*, builtins.str*]' + x: RequiresContextFutureResult[float, bool, str] + reveal_type(bind(test)(x)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult*[builtins.int*, builtins.bool*, builtins.str*]' - case: bind_future @@ -137,7 +158,8 @@ def test(arg: float) -> Future[int]: ... - reveal_type(bind(test)) # N: Revealed type is 'def (returns.future.Future[builtins.float*]) -> returns.future.Future[builtins.int*]' + x: Future[float] + reveal_type(bind(test)(x)) # N: Revealed type is 'returns.future.Future*[builtins.int*]' - case: bind_futureresult @@ -149,4 +171,35 @@ def test(arg: float) -> FutureResult[int, str]: ... - reveal_type(bind(test)) # N: Revealed type is 'def (returns.future.FutureResult[builtins.float*, builtins.str*]) -> returns.future.FutureResult[builtins.int*, builtins.str*]' + x: FutureResult[float, str] + reveal_type(bind(test)(x)) # N: Revealed type is 'returns.future.FutureResult*[builtins.int*, builtins.str*]' + + +- case: bind_custom_type + disable_cache: true + main: | + from returns.pointfree import bind + from returns.primitives.hkt import Kind1, dekind + from returns.interfaces.bindable import Bindable1 + from typing import Callable, TypeVar + + T = TypeVar('T') + N = TypeVar('N') + + class MyOwn( + Kind1['MyOwn', T], + Bindable1[T], + ): + def __init__(self, value: T) -> None: + self.value = value + + def bind( + self, function: Callable[[T], Kind1['MyOwn', N]], + ) -> 'MyOwn[N]': + return dekind(function(self.value)) + + def test(arg: float) -> MyOwn[int]: + ... + + x: MyOwn[float] + reveal_type(bind(test)(x)) # N: Revealed type is 'main.MyOwn*[builtins.int*]' diff --git a/typesafety/test_pointfree/test_bind_async.yml b/typesafety/test_pointfree/test_bind_async.yml deleted file mode 100644 index bb715d48c..000000000 --- a/typesafety/test_pointfree/test_bind_async.yml +++ /dev/null @@ -1,38 +0,0 @@ -- case: bind_async_future - disable_cache: true - main: | - from returns.pointfree import bind_async - from returns.future import Future - - async def test(arg: float) -> Future[int]: - ... - - x: Future[float] - reveal_type(bind_async(test)(x)) # N: Revealed type is 'returns.future.Future[builtins.int*]' - - -- case: bind_async_futureresult - disable_cache: true - main: | - from returns.pointfree import bind_async - from returns.future import FutureResult - - async def test(arg: float) -> FutureResult[int, str]: - ... - - x: FutureResult[float, str] - reveal_type(bind_async(test)(x)) # N: Revealed type is 'returns.future.FutureResult[builtins.int*, builtins.str*]' - - -- case: bind_async_requires_context_future_result - disable_cache: true - main: | - from returns.pointfree import bind_async - from returns.context import RequiresContextFutureResult - - async def test(arg: int) -> RequiresContextFutureResult[bool, float, str]: - ... - - first: RequiresContextFutureResult[bool, int, str] - - reveal_type(bind_async(test)(first)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.float*, builtins.str*]' diff --git a/typesafety/test_pointfree/test_bind_async_future.yml b/typesafety/test_pointfree/test_bind_async_future.yml deleted file mode 100644 index 6f8bb8d05..000000000 --- a/typesafety/test_pointfree/test_bind_async_future.yml +++ /dev/null @@ -1,43 +0,0 @@ -- case: bind_async_future_and_flow - disable_cache: true - main: | - from returns.functions import identity - from returns.pointfree import bind_async_future, bind - from returns.future import Future, FutureResult - from returns.pipeline import flow - - async def test(arg: int) -> Future[float]: - ... - - def second(arg: float) -> FutureResult[bool, str]: - ... - - r: FutureResult[int, str] - reveal_type(flow(r, bind_async_future(test), bind(second), identity)) # N: Revealed type is 'returns.future.FutureResult*[builtins.bool*, builtins.str*]' - - -- case: bind_async_future_futureresult - disable_cache: true - main: | - from returns.pointfree import bind_async_future - from returns.future import Future, FutureResult - - async def test(arg: float) -> Future[int]: - ... - - x: FutureResult[float, str] - reveal_type(bind_async_future(test)(x)) # N: Revealed type is 'returns.future.FutureResult[builtins.int, builtins.str*]' - - -- case: bind_async_future_requires_context_future_result - disable_cache: true - main: | - from returns.pointfree import bind_async_future - from returns.future import Future - from returns.context import ReaderFutureResult - - async def test(arg: float) -> Future[int]: - ... - - x: ReaderFutureResult[bool, float, Exception] - reveal_type(bind_async_future(test)(x)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.int, builtins.Exception*]' diff --git a/typesafety/test_pointfree/test_bind_async_future_result.yml b/typesafety/test_pointfree/test_bind_async_future_result.yml deleted file mode 100644 index 6e469c0af..000000000 --- a/typesafety/test_pointfree/test_bind_async_future_result.yml +++ /dev/null @@ -1,28 +0,0 @@ -- case: bind_async_future_and_flow - disable_cache: true - main: | - from returns.functions import identity - from returns.pointfree import bind_async_future_result - from returns.future import FutureResult - from returns.context import ReaderFutureResult - from returns.pipeline import flow - - async def test(arg: int) -> FutureResult[float, str]: - ... - - r: ReaderFutureResult[object, int, str] - reveal_type(flow(r, bind_async_future_result(test), identity)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult*[builtins.object*, builtins.float, builtins.str]' - - -- case: bind_async_future_result_requires_context_future_result - disable_cache: true - main: | - from returns.pointfree import bind_async_future_result - from returns.future import FutureResult - from returns.context import ReaderFutureResult - - async def test(arg: float) -> FutureResult[int, Exception]: - ... - - x: ReaderFutureResult[bool, float, Exception] - reveal_type(bind_async_future_result(test)(x)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.int, builtins.Exception]' diff --git a/typesafety/test_pointfree/test_bind_awaitable.yml b/typesafety/test_pointfree/test_bind_awaitable.yml deleted file mode 100644 index aca725434..000000000 --- a/typesafety/test_pointfree/test_bind_awaitable.yml +++ /dev/null @@ -1,56 +0,0 @@ -- case: bind_awaitable_and_flow - disable_cache: true - main: | - from returns.future import FutureResult - from returns.functions import identity - from returns.pointfree import bind_awaitable - from returns.pipeline import flow - - async def test(arg: int) -> float: - ... - - async def second(arg: float) -> bool: - ... - - r: FutureResult[int, str] - reveal_type(flow(r, bind_awaitable(test), bind_awaitable(second), identity)) # N: Revealed type is 'returns.future.FutureResult*[builtins.bool, builtins.str*]' - - -- case: bind_awaitable_future - disable_cache: true - main: | - from returns.pointfree import bind_awaitable - from returns.future import Future - - async def test(arg: float) -> int: - ... - - x: Future[float] - reveal_type(bind_awaitable(test)(x)) # N: Revealed type is 'returns.future.Future[builtins.int*]' - - -- case: bind_awaitable_futureresult - disable_cache: true - main: | - from returns.pointfree import bind_awaitable - from returns.future import FutureResult - - async def test(arg: float) -> int: - ... - - x: FutureResult[float, str] - reveal_type(bind_awaitable(test)(x)) # N: Revealed type is 'returns.future.FutureResult[builtins.int, builtins.str*]' - - -- case: bind_awaitable_requires_context_future_result - disable_cache: true - main: | - from returns.pointfree import bind_awaitable - from returns.context import RequiresContextFutureResult - - async def test(arg: int) -> float: - ... - - first: RequiresContextFutureResult[bool, int, str] - - reveal_type(bind_awaitable(test)(first)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.float, builtins.str*]' diff --git a/typesafety/test_pointfree/test_bind_context.yml b/typesafety/test_pointfree/test_bind_context.yml deleted file mode 100644 index 1998b4ead..000000000 --- a/typesafety/test_pointfree/test_bind_context.yml +++ /dev/null @@ -1,71 +0,0 @@ -- case: bind_context_wrong_env - disable_cache: true - main: | - from returns.pointfree import bind_context - from returns.context import RequiresContext, RequiresContextResult - - def test(arg: float) -> RequiresContext[str, int]: - ... - - x: RequiresContextResult[bool, float, str] - reveal_type(bind_context(test)(x)) - out: | - main:8: error: Argument 1 to "__call__" of "_BindContext" has incompatible type "RequiresContextResult[bool, float, str]"; expected "RequiresContextResult[str, float, str]" - main:8: note: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.str, builtins.int, builtins.str*]' - - -- case: bind_context_and_flow - disable_cache: true - main: | - from returns.context import RequiresContext, RequiresContextResult - from returns.functions import identity - from returns.pointfree import bind_context - from returns.pipeline import flow - - def test(arg: int) -> RequiresContext[object, float]: - ... - - def second(arg: float) -> RequiresContext[object, bool]: - ... - - r: RequiresContextResult[object, int, str] - reveal_type(flow(r, bind_context(test), bind_context(second), identity)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult*[builtins.object, builtins.bool, builtins.str*]' - - -- case: bind_context_requires_context_result - disable_cache: true - main: | - from returns.pointfree import bind_context - from returns.context import RequiresContext, RequiresContextResult - - def test(arg: float) -> RequiresContext[bool, int]: - ... - - x: RequiresContextResult[bool, float, str] - reveal_type(bind_context(test)(x)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.bool, builtins.int, builtins.str*]' - - -- case: bind_context_requires_context_ioresult - disable_cache: true - main: | - from returns.pointfree import bind_context - from returns.context import RequiresContext, RequiresContextIOResult - - def test(arg: float) -> RequiresContext[bool, int]: - ... - - x: RequiresContextIOResult[bool, float, str] - reveal_type(bind_context(test)(x)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.bool, builtins.int, builtins.str*]' - - -- case: bind_context_requires_context_future_result - disable_cache: true - main: | - from returns.pointfree import bind_context - from returns.context import RequiresContext, RequiresContextFutureResult - - def test(arg: float) -> RequiresContext[bool, int]: - ... - - x: RequiresContextFutureResult[bool, float, str] - reveal_type(bind_context(test)(x)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool, builtins.int, builtins.str*]' diff --git a/typesafety/test_pointfree/test_bind_context_ioresult.yml b/typesafety/test_pointfree/test_bind_context_ioresult.yml deleted file mode 100644 index 4e58f07fb..000000000 --- a/typesafety/test_pointfree/test_bind_context_ioresult.yml +++ /dev/null @@ -1,29 +0,0 @@ -- case: bind_context_ioresult_and_flow - disable_cache: true - main: | - from returns.context import RequiresContextFutureResult, RequiresContextIOResult - from returns.functions import identity - from returns.pointfree import bind_context_ioresult - from returns.pipeline import flow - - def test(arg: int) -> RequiresContextIOResult[object, float, str]: - ... - - def second(arg: float) -> RequiresContextIOResult[object, bool, str]: - ... - - r: RequiresContextFutureResult[object, int, str] - reveal_type(flow(r, bind_context_ioresult(test), bind_context_ioresult(second), identity)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult*[builtins.object*, builtins.bool*, builtins.str*]' - - -- case: bind_context_ioresult_requires_context_future_result - disable_cache: true - main: | - from returns.pointfree import bind_context_ioresult - from returns.context import RequiresContextIOResult, RequiresContextFutureResult - - def test(arg: float) -> RequiresContextIOResult[bool, int, str]: - ... - - x: RequiresContextFutureResult[bool, float, str] - reveal_type(bind_context_ioresult(test)(x)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.int*, builtins.str*]' diff --git a/typesafety/test_pointfree/test_bind_context_result.yml b/typesafety/test_pointfree/test_bind_context_result.yml deleted file mode 100644 index af9b51f45..000000000 --- a/typesafety/test_pointfree/test_bind_context_result.yml +++ /dev/null @@ -1,74 +0,0 @@ -- case: bind_context_result_wrong_env - disable_cache: true - main: | - from returns.pointfree import bind_context_result - from returns.context import RequiresContextResult, RequiresContextIOResult - - def test(arg: float) -> RequiresContextResult[str, int, str]: - ... - - x: RequiresContextIOResult[bool, float, str] - reveal_type(bind_context_result(test)(x)) - out: | - main:8: error: Argument 1 to "__call__" of "_BindContextResult" has incompatible type "RequiresContextIOResult[bool, float, str]"; expected "RequiresContextIOResult[str, float, str]" - main:8: note: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.str*, builtins.int*, builtins.str*]' - - -- case: bind_context_result_wrong_error - disable_cache: true - main: | - from returns.pointfree import bind_context_result - from returns.context import RequiresContextResult, RequiresContextIOResult - - def test(arg: float) -> RequiresContextResult[str, int, str]: - ... - - x: RequiresContextIOResult[str, float, bool] - reveal_type(bind_context_result(test)(x)) - out: | - main:8: error: Argument 1 to "__call__" of "_BindContextResult" has incompatible type "RequiresContextIOResult[str, float, bool]"; expected "RequiresContextIOResult[str, float, str]" - main:8: note: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.str*, builtins.int*, builtins.str*]' - - -- case: bind_context_result_and_flow - disable_cache: true - main: | - from returns.context import RequiresContextResult, RequiresContextIOResult - from returns.functions import identity - from returns.pointfree import bind_context_result - from returns.pipeline import flow - - def test(arg: int) -> RequiresContextResult[object, float, str]: - ... - - def second(arg: float) -> RequiresContextResult[object, bool, str]: - ... - - r: RequiresContextIOResult[object, int, str] - reveal_type(flow(r, bind_context_result(test), bind_context_result(second), identity)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult*[builtins.object*, builtins.bool*, builtins.str*]' - - -- case: bind_context_result_requires_context_ioresult - disable_cache: true - main: | - from returns.pointfree import bind_context_result - from returns.context import RequiresContextResult, RequiresContextIOResult - - def test(arg: float) -> RequiresContextResult[bool, int, str]: - ... - - x: RequiresContextIOResult[bool, float, str] - reveal_type(bind_context_result(test)(x)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.bool*, builtins.int*, builtins.str*]' - - -- case: bind_context_result_requires_context_future_result - disable_cache: true - main: | - from returns.pointfree import bind_context_result - from returns.context import RequiresContextResult, RequiresContextFutureResult - - def test(arg: float) -> RequiresContextResult[bool, int, str]: - ... - - x: RequiresContextFutureResult[bool, float, str] - reveal_type(bind_context_result(test)(x)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.int*, builtins.str*]' diff --git a/typesafety/test_pointfree/test_bind_future.yml b/typesafety/test_pointfree/test_bind_future.yml deleted file mode 100644 index 5cb059869..000000000 --- a/typesafety/test_pointfree/test_bind_future.yml +++ /dev/null @@ -1,43 +0,0 @@ -- case: bind_future_and_flow - disable_cache: true - main: | - from returns.functions import identity - from returns.pointfree import bind_future, bind - from returns.future import Future, FutureResult - from returns.pipeline import flow - - def test(arg: int) -> Future[float]: - ... - - def second(arg: float) -> FutureResult[bool, str]: - ... - - r: FutureResult[int, str] - reveal_type(flow(r, bind_future(test), bind(second), identity)) # N: Revealed type is 'returns.future.FutureResult*[builtins.bool*, builtins.str*]' - - -- case: bind_future_futureresult - disable_cache: true - main: | - from returns.pointfree import bind_future - from returns.future import Future, FutureResult - - def test(arg: float) -> Future[int]: - ... - - x: FutureResult[float, str] - reveal_type(bind_future(test)(x)) # N: Revealed type is 'returns.future.FutureResult[builtins.int, builtins.str*]' - - -- case: bind_future_requires_context_future_result - disable_cache: true - main: | - from returns.pointfree import bind_future - from returns.future import Future - from returns.context import ReaderFutureResult - - def test(arg: float) -> Future[int]: - ... - - x: ReaderFutureResult[bool, float, Exception] - reveal_type(bind_future(test)(x)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.int, builtins.Exception*]' diff --git a/typesafety/test_pointfree/test_bind_future_result.yml b/typesafety/test_pointfree/test_bind_future_result.yml deleted file mode 100644 index dffcc2105..000000000 --- a/typesafety/test_pointfree/test_bind_future_result.yml +++ /dev/null @@ -1,31 +0,0 @@ -- case: bind_future_result_and_flow - disable_cache: true - main: | - from returns.functions import identity - from returns.pointfree import bind_future_result, bind - from returns.future import FutureResultE - from returns.context import ReaderFutureResultE - from returns.pipeline import flow - - def test(arg: int) -> FutureResultE[float]: - ... - - def second(arg: float) -> ReaderFutureResultE[bool, str]: - ... - - r: ReaderFutureResultE[bool, int] - reveal_type(flow(r, bind_future_result(test), bind(second), identity)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult*[builtins.bool*, builtins.str*, builtins.Exception*]' - - -- case: bind_future_result_requires_context_future_result - disable_cache: true - main: | - from returns.pointfree import bind_future_result - from returns.future import FutureResultE - from returns.context import ReaderFutureResultE - - def test(arg: float) -> FutureResultE[int]: - ... - - x: ReaderFutureResultE[bool, float] - reveal_type(bind_future_result(test)(x)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.int, builtins.Exception]' diff --git a/typesafety/test_pointfree/test_bind_io.yml b/typesafety/test_pointfree/test_bind_io.yml deleted file mode 100644 index 61a1df84c..000000000 --- a/typesafety/test_pointfree/test_bind_io.yml +++ /dev/null @@ -1,85 +0,0 @@ -- case: bind_io_and_flow - disable_cache: true - main: | - from returns.io import IO, IOResult - from returns.functions import identity - from returns.pointfree import bind_io - from returns.pipeline import flow - - def test(arg: int) -> IO[float]: - ... - - def second(arg: float) -> IO[bool]: - ... - - r: IOResult[int, str] - reveal_type(flow(r, bind_io(test), bind_io(second), identity)) # N: Revealed type is 'returns.io.IOResult*[builtins.bool, builtins.str*]' - - -- case: bind_io_ioresult - disable_cache: true - main: | - from returns.pointfree import bind_io - from returns.io import IO, IOResult - - def test(arg: float) -> IO[int]: - ... - - x: IOResult[float, str] - reveal_type(bind_io(test)(x)) # N: Revealed type is 'returns.io.IOResult[builtins.int, builtins.str*]' - - -- case: bind_io_requires_context_ioresult - disable_cache: true - main: | - from returns.pointfree import bind_io - from returns.context import RequiresContextIOResult - from returns.io import IO - - def test(arg: float) -> IO[int]: - ... - - x: RequiresContextIOResult[bool, float, str] - reveal_type(bind_io(test)(x)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.bool*, builtins.int, builtins.str*]' - - -- case: bind_io_requires_context_future_result - disable_cache: true - main: | - from returns.pointfree import bind_io - from returns.context import RequiresContextFutureResult - from returns.io import IO - - def test(arg: float) -> IO[int]: - ... - - x: RequiresContextFutureResult[bool, float, str] - reveal_type(bind_io(test)(x)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.int, builtins.str*]' - - -- case: bind_io_future - disable_cache: true - main: | - from returns.pointfree import bind_io - from returns.future import Future - from returns.io import IO - - def test(arg: float) -> IO[int]: - ... - - x: Future[float] - reveal_type(bind_io(test)(x)) # N: Revealed type is 'returns.future.Future[builtins.int*]' - - -- case: bind_io_futureresult - disable_cache: true - main: | - from returns.pointfree import bind_io - from returns.future import FutureResult - from returns.io import IO - - def test(arg: float) -> IO[int]: - ... - - x: FutureResult[float, str] - reveal_type(bind_io(test)(x)) # N: Revealed type is 'returns.future.FutureResult[builtins.int, builtins.str*]' diff --git a/typesafety/test_pointfree/test_bind_ioresult.yml b/typesafety/test_pointfree/test_bind_ioresult.yml deleted file mode 100644 index bc91dc36f..000000000 --- a/typesafety/test_pointfree/test_bind_ioresult.yml +++ /dev/null @@ -1,76 +0,0 @@ -- case: bind_ioresult_and_flow - disable_cache: true - main: | - from returns.io import IOResult - from returns.future import FutureResult - from returns.functions import identity - from returns.pointfree import bind_ioresult - from returns.pipeline import flow - - def test(arg: int) -> IOResult[float, str]: - ... - - def second(arg: float) -> IOResult[bool, str]: - ... - - r: FutureResult[int, str] - reveal_type(flow(r, bind_ioresult(test), bind_ioresult(second), identity)) # N: Revealed type is 'returns.future.FutureResult*[builtins.bool*, builtins.str*]' - - -- case: bind_ioresult_wrong - disable_cache: true - main: | - from returns.pointfree import bind_ioresult - from returns.future import FutureResult - from returns.io import IOResult - - def test(arg: float) -> IOResult[int, Exception]: - ... - - x: FutureResult[float, str] - reveal_type(bind_ioresult(test)(x)) - out: | - main:9: error: Argument 1 to "__call__" of "_BindIOResult" has incompatible type "FutureResult[float, str]"; expected "FutureResult[float, Exception]" - main:9: note: Revealed type is 'returns.future.FutureResult[builtins.int*, builtins.Exception*]' - - -- case: bind_ioresult_requires_context_ioresult - disable_cache: true - main: | - from returns.pointfree import bind_ioresult - from returns.context import RequiresContextIOResult - from returns.io import IOResult - - def test(arg: float) -> IOResult[int, str]: - ... - - x: RequiresContextIOResult[bool, float, str] - reveal_type(bind_ioresult(test)(x)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.bool*, builtins.int, builtins.str]' - - -- case: bind_ioresult_requires_context_future_result - disable_cache: true - main: | - from returns.pointfree import bind_ioresult - from returns.context import RequiresContextFutureResult - from returns.io import IOResult - - def test(arg: float) -> IOResult[int, str]: - ... - - x: RequiresContextFutureResult[bool, float, str] - reveal_type(bind_ioresult(test)(x)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.int, builtins.str]' - - -- case: bind_ioresult_futureresult - disable_cache: true - main: | - from returns.pointfree import bind_ioresult - from returns.future import FutureResult - from returns.io import IOResult - - def test(arg: float) -> IOResult[int, str]: - ... - - x: FutureResult[float, str] - reveal_type(bind_ioresult(test)(x)) # N: Revealed type is 'returns.future.FutureResult[builtins.int*, builtins.str*]' diff --git a/typesafety/test_pointfree/test_bind_result.yml b/typesafety/test_pointfree/test_bind_result.yml index 59a35f67d..14a8eb1a1 100644 --- a/typesafety/test_pointfree/test_bind_result.yml +++ b/typesafety/test_pointfree/test_bind_result.yml @@ -14,7 +14,35 @@ ... r: IOResult[int, str] - reveal_type(flow(r, bind_result(test), bind_result(second), identity)) # N: Revealed type is 'returns.io.IOResult*[builtins.bool*, builtins.str*]' + reveal_type(flow(r, bind_result(test), bind_result(second))) # N: Revealed type is 'returns.io.IOResult*[builtins.bool, builtins.str]' + + +- case: bind_result_wrong_first_type + disable_cache: true + main: | + from returns.pointfree import bind_result + from returns.context import RequiresContextFutureResult + from returns.result import Result + + def test(arg: float) -> Result[int, str]: + ... + + x: RequiresContextFutureResult[str, int, bool] + bind_result(test)(x) # E: Argument 1 has incompatible type "RequiresContextFutureResult[str, int, bool]"; expected "KindN[RequiresContextFutureResult[Any, Any, Any], float, str, bool]" + + +- case: bind_result_wrong_second_type + disable_cache: true + main: | + from returns.pointfree import bind_result + from returns.context import RequiresContextFutureResult + from returns.result import Result + + def test(arg: float) -> Result[int, str]: + ... + + x: RequiresContextFutureResult[float, int, bool] + bind_result(test)(x) # E: Argument 1 has incompatible type "RequiresContextFutureResult[float, int, bool]"; expected "KindN[RequiresContextFutureResult[Any, Any, Any], float, str, bool]" - case: bind_result_ioresult @@ -28,7 +56,7 @@ ... x: IOResult[float, str] - reveal_type(bind_result(test)(x)) # N: Revealed type is 'returns.io.IOResult[builtins.int*, builtins.str*]' + reveal_type(bind_result(test)(x)) # N: Revealed type is 'returns.io.IOResult*[builtins.int, builtins.str]' - case: bind_result_requires_context_result @@ -41,8 +69,8 @@ def test(arg: float) -> Result[int, str]: ... - x: RequiresContextResult[bool, float, str] - reveal_type(bind_result(test)(x)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.bool*, builtins.int, builtins.str]' + x: RequiresContextResult[float, str, bool] + reveal_type(bind_result(test)(x)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult*[builtins.int, builtins.str, builtins.bool*]' - case: bind_result_requires_context_ioresult @@ -55,8 +83,8 @@ def test(arg: float) -> Result[int, str]: ... - x: RequiresContextIOResult[bool, float, str] - reveal_type(bind_result(test)(x)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.bool*, builtins.int, builtins.str]' + x: RequiresContextIOResult[float, str, bool] + reveal_type(bind_result(test)(x)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult*[builtins.int, builtins.str, builtins.bool*]' - case: bind_result_requires_context_future_result @@ -69,8 +97,8 @@ def test(arg: float) -> Result[int, str]: ... - x: RequiresContextFutureResult[bool, float, str] - reveal_type(bind_result(test)(x)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.int, builtins.str]' + x: RequiresContextFutureResult[float, str, bool] + reveal_type(bind_result(test)(x)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult*[builtins.int, builtins.str, builtins.bool*]' - case: bind_result_futureresult @@ -84,4 +112,52 @@ ... x: FutureResult[float, str] - reveal_type(bind_result(test)(x)) # N: Revealed type is 'returns.future.FutureResult[builtins.int*, builtins.str*]' + reveal_type(bind_result(test)(x)) # N: Revealed type is 'returns.future.FutureResult*[builtins.int, builtins.str]' + + +- case: bind_result_custom_type + disable_cache: true + main: | + from typing import Callable, TypeVar, Any + from returns.interfaces.specific.result import ResultBased2 + from returns.primitives.hkt import Kind2 + from returns.result import Result + from returns.pointfree import bind_result + + _ValueType = TypeVar('_ValueType') + _NewValueType = TypeVar('_NewValueType') + + # Result related: + _ErrorType = TypeVar('_ErrorType') + _NewErrorType = TypeVar('_NewErrorType') + + class MyClass( + Kind2['MyClass', _ValueType, _ErrorType], + ResultBased2[_ValueType, _ErrorType], + ): + def bind_result( + self, + function: Callable[ + [_ValueType], + Result[_NewValueType, _ErrorType], + ], + ) -> MyClass[_NewValueType, _ErrorType]: + ... + + @classmethod + def from_result( + self, inner_value: Result[_NewValueType, _NewErrorType], + ) -> MyClass[_NewValueType, _NewErrorType]: + ... + + @classmethod + def from_failure( + cls, inner_value: _NewErrorType, + ) -> MyClass[Any, _NewErrorType]: + ... + + def test(a: int) -> Result[float, str]: + ... + + x: MyClass[int, str] + reveal_type(bind_result(test)(x)) # N: Revealed type is 'main.MyClass*[builtins.float, builtins.str]' diff --git a/typesafety/test_pointfree/test_fix.yml b/typesafety/test_pointfree/test_fix.yml deleted file mode 100644 index 19589ff72..000000000 --- a/typesafety/test_pointfree/test_fix.yml +++ /dev/null @@ -1,141 +0,0 @@ -- case: fix_variance - disable_cache: true - main: | - from returns.pointfree import fix - from returns.result import Result - - class A: ... - class B(A): ... - class C(B): ... - - x: Result[str, B] - - def test(a: A) -> C: - ... - - # TODO: this is probably a bug in mypy. - # Should be `Result[main.C, main.B]` - reveal_type(fix(test)(x)) # N: Revealed type is 'returns.result.Result[main.C, main.A]' - - -- case: fix_callback_protocol - disable_cache: true - main: | - from typing import Callable, TypeVar - from returns.pointfree import fix - from returns.result import Result - - _ValueType = TypeVar('_ValueType', contravariant=True) - _NewValueType = TypeVar('_NewValueType', covariant=True) - _ErrorType = TypeVar('_ErrorType', contravariant=True) - - def ensure_callback( - f: Callable[ - [Result[_ValueType, _ErrorType]], - Result[_NewValueType, _ErrorType], - ], - c: Result[_ValueType, _ErrorType], - ) -> Result[_NewValueType, _ErrorType]: - return f(c) - - def test(arg: int) -> float: - return arg + 1.5 - - x: Result[str, int] - reveal_type(ensure_callback(fix(test), x)) # N: Revealed type is 'returns.result.Result[builtins.float*, builtins.int]' - - -- case: fix_and_flow - disable_cache: true - main: | - from returns.result import Result - from returns.functions import identity - from returns.pointfree import alt, fix - from returns.pipeline import flow - - def test(arg: int) -> float: - ... - - def stringify(arg: float) -> str: - ... - - r: Result[bool, int] - reveal_type(flow(r, alt(test), fix(stringify), identity)) # N: Revealed type is 'returns.result.Result*[builtins.str, builtins.float]' - - -- case: fix_result - disable_cache: true - main: | - from returns.pointfree import fix - from returns.result import Result - - def test(arg: float) -> int: - ... - - x: Result[str, float] - reveal_type(fix(test)(x)) # N: Revealed type is 'returns.result.Result[builtins.int, builtins.float]' - - -- case: fix_ioresult - disable_cache: true - main: | - from returns.pointfree import fix - from returns.io import IOResult - - def test(arg: float) -> int: - ... - - x: IOResult[str, float] - reveal_type(fix(test)(x)) # N: Revealed type is 'returns.io.IOResult[builtins.int, builtins.float]' - - -- case: fix_requires_context_result - disable_cache: true - main: | - from returns.pointfree import fix - from returns.context import RequiresContextResult - - def test(arg: float) -> int: - ... - - x: RequiresContextResult[bool, str, float] - reveal_type(fix(test)(x)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.bool*, builtins.int, builtins.float]' - - -- case: fix_requires_context_ioresult - disable_cache: true - main: | - from returns.pointfree import fix - from returns.context import RequiresContextIOResult - - def test(arg: float) -> int: - ... - - x: RequiresContextIOResult[bool, str, float] - reveal_type(fix(test)(x)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.bool*, builtins.int, builtins.float]' - - -- case: fix_requires_context_future_result - disable_cache: true - main: | - from returns.pointfree import fix - from returns.context import RequiresContextFutureResult - - def test(arg: float) -> int: - ... - - x: RequiresContextFutureResult[bool, str, float] - reveal_type(fix(test)(x)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.int, builtins.float]' - - -- case: fix_futureresult - disable_cache: true - main: | - from returns.pointfree import fix - from returns.future import FutureResult - - def test(arg: float) -> int: - ... - - x: FutureResult[str, float] - reveal_type(fix(test)(x)) # N: Revealed type is 'returns.future.FutureResult[builtins.int, builtins.float]' diff --git a/typesafety/test_pointfree/test_map.yml b/typesafety/test_pointfree/test_map.yml index f2baf87de..5ff5a48bc 100644 --- a/typesafety/test_pointfree/test_map.yml +++ b/typesafety/test_pointfree/test_map.yml @@ -13,7 +13,7 @@ def test(a: A) -> C: ... - reveal_type(map_(test)(x)) # N: Revealed type is 'returns.maybe.Maybe[main.C*]' + reveal_type(map_(test)(x)) # N: Revealed type is 'returns.maybe.Maybe*[main.C]' - case: map_callback_protocol @@ -21,15 +21,21 @@ main: | from typing import Callable, TypeVar from returns.pointfree import map_ + from returns.primitives.hkt import KindN, kinded + from returns.interfaces.mappable import MappableN from returns.maybe import Maybe - _ValueType = TypeVar('_ValueType', contravariant=True) - _NewValueType = TypeVar('_NewValueType', covariant=True) + _T1 = TypeVar('_T1') + _T2 = TypeVar('_T2') + _T3 = TypeVar('_T3') + _U1 = TypeVar('_U1') + _Inst = TypeVar('_Inst', bound=MappableN) + @kinded def ensure_callback( - f: Callable[[Maybe[_ValueType]], Maybe[_NewValueType]], - c: Maybe[_ValueType], - ) -> Maybe[_NewValueType]: + f: Callable[[KindN[_Inst, _T1, _T2, _T3]], KindN[_Inst, _U1, _T2, _T3]], + c: KindN[_Inst, _T1, _T2, _T3], + ) -> KindN[_Inst, _U1, _T2, _T3]: return f(c) def test(arg: int) -> float: @@ -66,7 +72,7 @@ def test(arg: int) -> Result[float, str]: ... - reveal_type(map_(bind(test))(IO(Success(1)))) # N: Revealed type is 'returns.io.IO[returns.result.Result*[builtins.float*, builtins.str*]]' + reveal_type(map_(bind(test))(IO(Success(1)))) # N: Revealed type is 'returns.io.IO*[returns.result.Result[builtins.float, builtins.str]]' - case: map_io @@ -78,7 +84,7 @@ def test(arg: float) -> int: ... - reveal_type(map_(test)(IO(1.5))) # N: Revealed type is 'returns.io.IO[builtins.int*]' + reveal_type(map_(test)(IO(1.5))) # N: Revealed type is 'returns.io.IO*[builtins.int]' - case: map_maybe @@ -90,7 +96,7 @@ def test(arg: float) -> int: ... - reveal_type(map_(test)(Maybe.from_value(1.5))) # N: Revealed type is 'returns.maybe.Maybe[builtins.int*]' + reveal_type(map_(test)(Maybe.from_value(1.5))) # N: Revealed type is 'returns.maybe.Maybe*[builtins.int]' - case: map_result @@ -103,7 +109,7 @@ ... x: Result[float, str] - reveal_type(map_(test)(x)) # N: Revealed type is 'returns.result.Result[builtins.int, builtins.str*]' + reveal_type(map_(test)(x)) # N: Revealed type is 'returns.result.Result*[builtins.int, builtins.str*]' - case: map_ioresult @@ -116,7 +122,7 @@ ... x: IOResult[float, str] - reveal_type(map_(test)(x)) # N: Revealed type is 'returns.io.IOResult[builtins.int, builtins.str*]' + reveal_type(map_(test)(x)) # N: Revealed type is 'returns.io.IOResult*[builtins.int, builtins.str*]' - case: map_requires_context @@ -128,8 +134,8 @@ def test(arg: float) -> int: ... - x: RequiresContext[str, float] - reveal_type(map_(test)(x)) # N: Revealed type is 'returns.context.requires_context.RequiresContext[builtins.str*, builtins.int]' + x: RequiresContext[float, str] + reveal_type(map_(test)(x)) # N: Revealed type is 'returns.context.requires_context.RequiresContext*[builtins.int, builtins.str*]' - case: map_requires_context_result @@ -141,8 +147,8 @@ def test(arg: float) -> int: ... - x: RequiresContextResult[bool, float, str] - reveal_type(map_(test)(x)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.bool*, builtins.int, builtins.str*]' + x: RequiresContextResult[float, str, bool] + reveal_type(map_(test)(x)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult*[builtins.int, builtins.str*, builtins.bool*]' - case: map_requires_context_ioresult @@ -154,8 +160,8 @@ def test(arg: float) -> int: ... - x: RequiresContextIOResult[bool, float, str] - reveal_type(map_(test)(x)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.bool*, builtins.int, builtins.str*]' + x: RequiresContextIOResult[float, str, bool] + reveal_type(map_(test)(x)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult*[builtins.int, builtins.str*, builtins.bool*]' - case: map_requires_context_future_result @@ -167,8 +173,8 @@ def test(arg: float) -> int: ... - x: RequiresContextFutureResult[bool, float, str] - reveal_type(map_(test)(x)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.bool*, builtins.int, builtins.str*]' + x: RequiresContextFutureResult[float, str, bool] + reveal_type(map_(test)(x)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult*[builtins.int, builtins.str*, builtins.bool*]' - case: map_future @@ -180,7 +186,7 @@ def test(arg: float) -> int: ... - reveal_type(map_(test)(Future.from_value(1.5))) # N: Revealed type is 'returns.future.Future[builtins.int*]' + reveal_type(map_(test)(Future.from_value(1.5))) # N: Revealed type is 'returns.future.Future*[builtins.int]' - case: map_futureresult @@ -193,4 +199,34 @@ ... x: FutureResult[float, str] - reveal_type(map_(test)(x)) # N: Revealed type is 'returns.future.FutureResult[builtins.int, builtins.str*]' + reveal_type(map_(test)(x)) # N: Revealed type is 'returns.future.FutureResult*[builtins.int, builtins.str*]' + + +- case: bind_custom_type + disable_cache: true + main: | + from returns.pointfree import bind + from returns.primitives.hkt import Kind1, dekind + from returns.interfaces.bindable import Bindable1 + from typing import Callable, TypeVar + + T = TypeVar('T') + N = TypeVar('N') + + class MyOwn( + Kind1['MyOwn', T], + Bindable1[T], + ): + def __init__(self, value: T) -> None: + self.value = value + + def bind( + self, function: Callable[[T], Kind1['MyOwn', N]], + ) -> 'MyOwn[N]': + return dekind(function(self.value)) + + def test(arg: float) -> MyOwn[int]: + ... + + x: MyOwn[float] + reveal_type(bind(test)(x)) # N: Revealed type is 'main.MyOwn*[builtins.int*]' diff --git a/typesafety/test_pointfree/test_rescue.yml b/typesafety/test_pointfree/test_rescue.yml index cb0c059ca..3e5c9a466 100644 --- a/typesafety/test_pointfree/test_rescue.yml +++ b/typesafety/test_pointfree/test_rescue.yml @@ -1,3 +1,29 @@ +- case: rescue_wrong_second_type + disable_cache: true + main: | + from returns.pointfree import rescue + from returns.context import RequiresContextIOResult + + def test(arg: float) -> RequiresContextIOResult[float, str, int]: + ... + + x: RequiresContextIOResult[float, str, int] + rescue(test)(x) # E: Argument 1 has incompatible type "RequiresContextIOResult[float, str, int]"; expected "KindN[RequiresContextIOResult[Any, Any, Any], float, float, int]" + + +- case: rescue_wrong_else_types + disable_cache: true + main: | + from returns.pointfree import rescue + from returns.context import RequiresContextIOResult + + def test(arg: float) -> RequiresContextIOResult[float, str, int]: + ... + + x: RequiresContextIOResult[str, float, str] + rescue(test)(x) # E: Argument 1 has incompatible type "RequiresContextIOResult[str, float, str]"; expected "KindN[RequiresContextIOResult[Any, Any, Any], float, float, int]" + + - case: rescue_result disable_cache: true main: | @@ -7,7 +33,8 @@ def test(arg: float) -> Result[int, str]: ... - reveal_type(rescue(test)) # N: Revealed type is 'def (returns.result.Result[builtins.int*, builtins.float*]) -> returns.result.Result[builtins.int*, builtins.str*]' + x: Result[int, float] + reveal_type(rescue(test)(x)) # N: Revealed type is 'returns.result.Result*[builtins.int*, builtins.str*]' - case: rescue_ioresult @@ -19,7 +46,8 @@ def test(arg: float) -> IOResult[int, str]: ... - reveal_type(rescue(test)) # N: Revealed type is 'def (returns.io.IOResult[builtins.int*, builtins.float*]) -> returns.io.IOResult[builtins.int*, builtins.str*]' + x: IOResult[int, float] + reveal_type(rescue(test)(x)) # N: Revealed type is 'returns.io.IOResult*[builtins.int*, builtins.str*]' - case: rescue_context_result @@ -28,10 +56,11 @@ from returns.pointfree import rescue from returns.context import RequiresContextResult - def test(arg: float) -> RequiresContextResult[int, float, str]: + def test(arg: float) -> RequiresContextResult[float, str, int]: ... - reveal_type(rescue(test)) # N: Revealed type is 'def (returns.context.requires_context_result.RequiresContextResult[builtins.int*, builtins.float*, builtins.float*]) -> returns.context.requires_context_result.RequiresContextResult[builtins.int*, builtins.float*, builtins.str*]' + x: RequiresContextResult[float, float, int] + reveal_type(rescue(test)(x)) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult*[builtins.float*, builtins.str*, builtins.int*]' - case: rescue_context_ioresult @@ -40,10 +69,11 @@ from returns.pointfree import rescue from returns.context import RequiresContextIOResult - def test(arg: float) -> RequiresContextIOResult[int, float, str]: + def test(arg: float) -> RequiresContextIOResult[float, str, int]: ... - reveal_type(rescue(test)) # N: Revealed type is 'def (returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.int*, builtins.float*, builtins.float*]) -> returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.int*, builtins.float*, builtins.str*]' + x: RequiresContextIOResult[float, float, int] + reveal_type(rescue(test)(x)) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult*[builtins.float*, builtins.str*, builtins.int*]' - case: rescue_context_future_result @@ -52,10 +82,11 @@ from returns.pointfree import rescue from returns.context import RequiresContextFutureResult - def test(arg: float) -> RequiresContextFutureResult[int, float, str]: + def test(arg: float) -> RequiresContextFutureResult[float, str, int]: ... - reveal_type(rescue(test)) # N: Revealed type is 'def (returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.int*, builtins.float*, builtins.float*]) -> returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.int*, builtins.float*, builtins.str*]' + x: RequiresContextFutureResult[float, float, int] + reveal_type(rescue(test)(x)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult*[builtins.float*, builtins.str*, builtins.int*]' - case: rescue_future_result @@ -67,4 +98,5 @@ def test(arg: float) -> FutureResult[int, str]: ... - reveal_type(rescue(test)) # N: Revealed type is 'def (returns.future.FutureResult[builtins.int*, builtins.float*]) -> returns.future.FutureResult[builtins.int*, builtins.str*]' + x: FutureResult[int, float] + reveal_type(rescue(test)(x)) # N: Revealed type is 'returns.future.FutureResult*[builtins.int*, builtins.str*]' diff --git a/typesafety/test_pointfree/test_unify.yml b/typesafety/test_pointfree/test_unify.yml deleted file mode 100644 index 24f3d283f..000000000 --- a/typesafety/test_pointfree/test_unify.yml +++ /dev/null @@ -1,43 +0,0 @@ -- case: unify_result - disable_cache: true - main: | - from returns.pointfree import unify - from returns.result import Result - - def test(arg: float) -> Result[int, str]: - ... - - x: Result[int, bool] - - reveal_type(unify(test)) # N: Revealed type is 'def [_ErrorType] (returns.result.Result[builtins.float*, _ErrorType`-4]) -> returns.result.Result[builtins.int*, Union[_ErrorType`-4, builtins.str*]]' - reveal_type(unify(test)(x)) # N: Revealed type is 'returns.result.Result[builtins.int, Union[builtins.bool*, builtins.str]]' - - -- case: unify_ioresult - disable_cache: true - main: | - from returns.pointfree import unify - from returns.io import IOResult - - def test(arg: float) -> IOResult[int, str]: - ... - - x: IOResult[int, bool] - - reveal_type(unify(test)) # N: Revealed type is 'def [_ErrorType] (returns.io.IOResult[builtins.float*, _ErrorType`-4]) -> returns.io.IOResult[builtins.int*, Union[_ErrorType`-4, builtins.str*]]' - reveal_type(unify(test)(x)) # N: Revealed type is 'returns.io.IOResult[builtins.int, Union[builtins.bool*, builtins.str]]' - - -- case: unify_ioresult - disable_cache: true - main: | - from returns.pointfree import unify - from returns.future import FutureResult - - def test(arg: float) -> FutureResult[int, str]: - ... - - x: FutureResult[int, bool] - - reveal_type(unify(test)) # N: Revealed type is 'def [_ErrorType] (returns.future.FutureResult[builtins.float*, _ErrorType`-4]) -> returns.future.FutureResult[builtins.int*, Union[_ErrorType`-4, builtins.str*]]' - reveal_type(unify(test)(x)) # N: Revealed type is 'returns.future.FutureResult[builtins.int, Union[builtins.bool*, builtins.str]]' diff --git a/typesafety/test_pointfree/test_value_or.yml b/typesafety/test_pointfree/test_value_or.yml deleted file mode 100644 index 1ac019b70..000000000 --- a/typesafety/test_pointfree/test_value_or.yml +++ /dev/null @@ -1,89 +0,0 @@ -- case: value_or_callback_protocol - disable_cache: true - main: | - from typing import Callable, TypeVar, Union - from returns.pointfree import value_or - from returns.maybe import Maybe - - _ValueType = TypeVar('_ValueType', contravariant=True) - _NewValueType = TypeVar('_NewValueType', covariant=True) - - def ensure_callback( - f: Callable[[Maybe[_ValueType]], Union[_ValueType, int]], - c: Maybe[_ValueType], - ) -> Union[_ValueType, int]: - return f(c) - - reveal_type(ensure_callback(value_or(1), Maybe.from_value('a'))) # N: Revealed type is 'Union[builtins.str, builtins.int]' - - -- case: value_or_and_flow - disable_cache: true - main: | - from returns.result import Result - from returns.functions import identity - from returns.pointfree import value_or - from returns.pipeline import flow - - r: Result[int, str] - reveal_type(flow(r, value_or(None), identity)) # N: Revealed type is 'Union[builtins.int*, None]' - - -- case: value_or_maybe - disable_cache: true - main: | - from returns.pointfree import value_or - from returns.maybe import Maybe - - x: Maybe[int] - reveal_type(value_or('a')(x)) # N: Revealed type is 'Union[builtins.int*, builtins.str]' - - -- case: value_or_result - disable_cache: true - main: | - from returns.pointfree import value_or - from returns.result import Result - - x: Result[int, bool] - reveal_type(value_or('a')(x)) # N: Revealed type is 'Union[builtins.int*, builtins.str]' - - -- case: value_or_ioresult - disable_cache: true - main: | - from returns.pointfree import value_or - from returns.io import IOResult - - x: IOResult[int, bool] - reveal_type(value_or('a')(x)) # N: Revealed type is 'returns.io.IO[Union[builtins.int*, builtins.str]]' - - -- case: value_or_context_result - disable_cache: true - main: | - from returns.pointfree import value_or - from returns.context import RequiresContextResult - - x: RequiresContextResult[object, int, bool] - reveal_type(value_or('a')(x)) # N: Revealed type is 'def (builtins.object*) -> Union[builtins.int*, builtins.str]' - - -- case: value_or_context_ioresult - disable_cache: true - main: | - from returns.pointfree import value_or - from returns.context import RequiresContextIOResult - - x: RequiresContextIOResult[object, int, bool] - reveal_type(value_or('a')(x)) # N: Revealed type is 'def (builtins.object*) -> returns.io.IO[Union[builtins.int*, builtins.str]]' - - -- case: value_or_context_future_result - disable_cache: true - main: | - from returns.pointfree import value_or - from returns.context import RequiresContextFutureResult - - x: RequiresContextFutureResult[object, int, bool] - reveal_type(value_or('a')(x)) # N: Revealed type is 'def (builtins.object*) -> typing.Awaitable[returns.io.IO[Union[builtins.int*, builtins.str]]]' diff --git a/typesafety/test_primitives/test_hkt/test_dekind/test_dekind.yml b/typesafety/test_primitives/test_hkt/test_dekind/test_dekind.yml new file mode 100644 index 000000000..d0fb4c924 --- /dev/null +++ b/typesafety/test_primitives/test_hkt/test_dekind/test_dekind.yml @@ -0,0 +1,72 @@ +- case: dekind_correct_fully_known + disable_cache: true + main: | + from returns.io import IO + from returns.primitives.hkt import Kind1, dekind + + container: Kind1[IO, int] + reveal_type(dekind(container)) # N: Revealed type is 'returns.io.IO[builtins.int]' + + +- case: dekind_bindable + disable_cache: true + main: | + from returns.interfaces.bindable import Bindable1 + from typing import Callable, TypeVar + from returns.primitives.hkt import Kind1, dekind + + T = TypeVar('T') + N = TypeVar('N') + + def bind( + instance: Bindable1[T], + function: Callable[[T], Kind1[Bindable1, N]], + ) -> Bindable1[N]: + x = dekind(instance.bind(function)) + reveal_type(x) # N: Revealed type is 'returns.interfaces.bindable.BindableN[N`-2, , ]' + return x + + +- case: dekind_correct_two_type_args + disable_cache: true + main: | + from returns.io import IOResult + from returns.primitives.hkt import Kind2, dekind + + container: Kind2[IOResult, int, str] + reveal_type(dekind(container)) # N: Revealed type is 'returns.io.IOResult[builtins.int, builtins.str]' + + +- case: dekind_correct_typevar + disable_cache: true + main: | + from typing import Callable, TypeVar + from returns.primitives.hkt import Kind1, dekind + + _ValueType = TypeVar('_ValueType') + _NewValueType = TypeVar('_NewValueType') + + class IO(Kind1['IO', _ValueType]): + def apply( + self, + container: Kind1[ + 'IO', Callable[[_ValueType], _NewValueType], + ], + ): + reveal_type(dekind(container)) # N: Revealed type is 'main.IO[def (_ValueType`1) -> _NewValueType`-1]' + + +- case: dekind_wrong_non_instance + disable_cache: true + main: | + from typing import TypeVar + from returns.primitives.hkt import Kind2, dekind + + T = TypeVar('T') + + def some(arg: T): + container: Kind2[T, int, str] + reveal_type(dekind(container)) + out: | + main:8: error: dekind must be used with Instance as the first type argument + main:8: note: Revealed type is 'Any' diff --git a/typesafety/test_primitives/test_hkt/test_kindn.yml b/typesafety/test_primitives/test_hkt/test_kindn.yml new file mode 100644 index 000000000..efc21c981 --- /dev/null +++ b/typesafety/test_primitives/test_hkt/test_kindn.yml @@ -0,0 +1,15 @@ +- case: kind_params + disable_cache: true + parametrized: + - count: 1 + expected: 2 + - count: 2 + expected: 3 + - count: 3 + expected: 4 + main: | + from returns.primitives.hkt import Kind{{ count }} + + container: Kind{{ count }}[object, int, str, bool, float] + out: | + main:3: error: Bad number of arguments for type alias, expected: {{ expected }}, given: 5