From bec8e13d8b2964d0d2e8022901a28595de7cc1fa Mon Sep 17 00:00:00 2001 From: sobolevn Date: Fri, 27 Dec 2024 21:23:19 +0300 Subject: [PATCH] Use wps@1.0.0 (#1993) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 42 + docs/conf.py | 12 +- docs/pages/converters.rst | 1 - poetry.lock | 931 +----------------- pyproject.toml | 148 ++- returns/_internal/futures/_future.py | 36 +- returns/_internal/futures/_future_result.py | 123 +-- .../futures/_reader_future_result.py | 40 +- returns/_internal/pipeline/managed.py | 12 +- returns/_internal/pipeline/pipe.pyi | 69 +- returns/context/requires_context.py | 64 +- .../context/requires_context_future_result.py | 249 +++-- returns/context/requires_context_ioresult.py | 133 +-- returns/context/requires_context_result.py | 118 ++- returns/contrib/hypothesis/_entrypoint.py | 16 +- returns/contrib/hypothesis/containers.py | 35 +- returns/contrib/hypothesis/laws.py | 49 +- returns/contrib/mypy/_consts.py | 3 +- returns/contrib/mypy/_features/curry.py | 40 +- returns/contrib/mypy/_features/do_notation.py | 10 +- returns/contrib/mypy/_features/flow.py | 2 +- returns/contrib/mypy/_features/kind.py | 15 +- returns/contrib/mypy/_features/partial.py | 27 +- returns/contrib/mypy/_features/pipe.py | 19 +- returns/contrib/mypy/_structures/args.py | 20 +- returns/contrib/mypy/_structures/types.py | 7 +- returns/contrib/mypy/_typeops/analtype.py | 43 +- returns/contrib/mypy/_typeops/fallback.py | 2 + returns/contrib/mypy/_typeops/inference.py | 21 +- .../mypy/_typeops/transform_callable.py | 65 +- returns/contrib/mypy/_typeops/visitor.py | 26 +- returns/contrib/mypy/returns_plugin.py | 6 +- returns/contrib/pytest/plugin.py | 74 +- returns/converters.py | 6 +- returns/curry.py | 19 +- returns/functions.py | 6 + returns/future.py | 350 ++++--- returns/interfaces/altable.py | 2 +- returns/interfaces/applicative.py | 2 +- returns/interfaces/container.py | 4 +- returns/interfaces/mappable.py | 2 +- returns/interfaces/specific/future.py | 11 +- returns/interfaces/specific/future_result.py | 7 +- returns/interfaces/specific/io.py | 2 +- returns/interfaces/specific/ioresult.py | 4 +- returns/interfaces/specific/maybe.py | 2 +- returns/interfaces/specific/reader.py | 9 +- .../specific/reader_future_result.py | 23 +- .../interfaces/specific/reader_ioresult.py | 10 +- returns/interfaces/specific/reader_result.py | 8 +- returns/interfaces/specific/result.py | 2 +- returns/interfaces/swappable.py | 4 +- returns/io.py | 182 ++-- returns/iterables.py | 45 +- returns/maybe.py | 59 +- returns/methods/cond.py | 16 +- returns/methods/partition.py | 16 +- returns/pointfree/alt.py | 12 +- returns/pointfree/apply.py | 12 +- returns/pointfree/bimap.py | 12 +- returns/pointfree/bind.py | 12 +- returns/pointfree/bind_async.py | 12 +- .../bind_async_context_future_result.py | 18 +- returns/pointfree/bind_async_future.py | 12 +- returns/pointfree/bind_async_future_result.py | 17 +- returns/pointfree/bind_awaitable.py | 12 +- returns/pointfree/bind_context.py | 24 +- .../pointfree/bind_context_future_result.py | 18 +- returns/pointfree/bind_context_ioresult.py | 12 +- returns/pointfree/bind_context_result.py | 12 +- returns/pointfree/bind_future.py | 12 +- returns/pointfree/bind_future_result.py | 17 +- returns/pointfree/bind_io.py | 26 +- returns/pointfree/bind_ioresult.py | 12 +- returns/pointfree/bind_optional.py | 12 +- returns/pointfree/bind_result.py | 12 +- returns/pointfree/compose_result.py | 17 +- returns/pointfree/cond.py | 25 +- returns/pointfree/lash.py | 12 +- returns/pointfree/map.py | 12 +- returns/pointfree/modify_env.py | 24 +- returns/pointfree/unify.py | 12 +- returns/primitives/asserts.py | 16 +- returns/primitives/container.py | 20 +- returns/primitives/hkt.py | 57 +- returns/primitives/laws.py | 11 +- returns/primitives/reawaitable.py | 4 +- returns/primitives/tracing.py | 19 +- returns/primitives/types.py | 6 +- returns/result.py | 124 +-- returns/trampolines.py | 4 +- returns/unsafe.py | 2 +- setup.cfg | 42 +- .../test_requires_context_ioresult_bind.py | 20 +- .../test_requires_context_result_bind.py | 15 +- .../test_laws/test_custom_type_applicative.py | 2 +- .../test_wrong_custom_type_with_init.py | 2 +- .../test_hypothesis/test_type_resolution.py | 1 - .../test_pytest/test_plugin_error_handler.py | 94 +- .../test_pytest/test_plugin_has_trace.py | 112 ++- tests/test_converters/test_flatten.py | 73 +- tests/test_curry/test_curry.py | 10 +- .../test_context/test_reader_future_result.py | 18 +- .../test_future/test_future_result.py | 8 +- .../test_ioresult_pattern_matching.py | 2 +- .../test_maybe/test_maybe_pattern_matching.py | 2 +- .../test_result_pattern_matching.py | 4 +- tests/test_functions/test_raise_exception.py | 16 +- .../test_future_decorator.py | 3 + .../test_future_result_decorator.py | 7 +- .../test_future_result_units.py | 6 +- tests/test_io/test_io_container/test_io.py | 11 +- .../test_io_container/test_io_pickle.py | 4 +- .../test_ioresult_bind.py | 10 +- .../test_impure_safe.py | 8 +- .../test_iterables/test_fold/test_collect.py | 223 +++-- .../test_fold/test_collect_all.py | 178 ++-- tests/test_iterables/test_fold/test_loop.py | 232 +++-- tests/test_maybe/test_maybe_bind.py | 5 +- tests/test_maybe/test_maybe_equality.py | 16 +- .../test_maybe_decorator.py | 3 +- tests/test_maybe/test_nothing_singleton.py | 2 +- tests/test_methods/test_partition.py | 39 +- tests/test_pattern_matching.py | 41 +- tests/test_pipeline/test_is_successful.py | 23 +- .../test_managed_future_result.py | 125 +-- .../test_managed/test_managed_ioresult.py | 125 +-- .../test_managed_reader_future_result.py | 125 +-- .../test_managed_reader_ioresult.py | 125 +-- .../test_asserts/test_assert_equal.py | 4 - .../test_base_container/test_pickle.py | 11 +- .../test_pickle_backward_deserialization.py | 6 +- .../test_lawful/test_laws_resolution.py | 28 +- tests/test_result/test_result_bind.py | 5 + tests/test_result/test_result_equality.py | 12 +- .../test_result_functions/test_safe.py | 1 - .../test_trampoline_decorator.py | 30 +- .../test_specific/test_io/test_io_like.yml | 3 +- typesafety/test_methods/test_partition.yml | 1 - .../test_tracing/test_collect_traces.yml | 4 +- 140 files changed, 2809 insertions(+), 2918 deletions(-) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 000000000..9f95a57ff --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,42 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - id: check-toml + - id: check-merge-conflict + - id: mixed-line-ending + args: [--fix=lf] + - id: check-case-conflict + - repo: https://github.com/python-jsonschema/check-jsonschema + rev: 0.30.0 + hooks: + - id: check-dependabot + - id: check-github-workflows + - repo: https://github.com/rhysd/actionlint + rev: v1.7.4 + hooks: + - id: actionlint + - repo: https://github.com/shellcheck-py/shellcheck-py + rev: v0.10.0.1 + hooks: + - id: shellcheck + - repo: https://github.com/tox-dev/pyproject-fmt + rev: v2.5.0 + hooks: + - id: pyproject-fmt + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.8.4 + hooks: + - id: ruff + args: ["--exit-non-zero-on-fix", "--fix"] + - id: ruff-format +exclude: ^(tests/fixtures/|tests/test_formatter/__snapshots__/) +ci: + autofix_commit_msg: "[pre-commit.ci] auto fixes from pre-commit.com hooks" + autofix_prs: true + autoupdate_commit_msg: "[pre-commit.ci] pre-commit autoupdate" + autoupdate_schedule: weekly + submodules: false diff --git a/docs/conf.py b/docs/conf.py index f4996e8de..bb98b56a8 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -10,24 +10,25 @@ # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -import os +import pathlib import sys import tomli -sys.path.insert(0, os.path.abspath('..')) +sys.path.insert(0, str(pathlib.Path('..').resolve())) # -- Project information ----------------------------------------------------- + def _get_project_meta(): - with open('../pyproject.toml', mode='rb') as pyproject: + with pathlib.Path('../pyproject.toml').open(mode='rb') as pyproject: return tomli.load(pyproject)['tool']['poetry'] pkg_meta = _get_project_meta() project = str(pkg_meta['name']) -copyright = '2019, dry-python team' # noqa: WPS125 +copyright = '2019, dry-python team' # noqa: A001 author = 'dry-python team' # The short X.Y version @@ -49,13 +50,10 @@ def _get_project_meta(): 'sphinx.ext.viewcode', 'sphinx.ext.autosummary', 'sphinx.ext.napoleon', - # Used to include .md files: 'myst_parser', - # Used to insert typehints into the final docs: 'sphinx_autodoc_typehints', - # Used to build graphs: 'sphinxcontrib.mermaid', ] diff --git a/docs/pages/converters.rst b/docs/pages/converters.rst index 35e60cdb5..883f8be20 100644 --- a/docs/pages/converters.rst +++ b/docs/pages/converters.rst @@ -63,4 +63,3 @@ API Reference .. automodule:: returns.converters :members: - diff --git a/poetry.lock b/poetry.lock index 183e77f1b..a9e560547 100644 --- a/poetry.lock +++ b/poetry.lock @@ -33,17 +33,6 @@ doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "truststore (>=0.9.1)", "uvloop (>=0.21)"] trio = ["trio (>=0.26.1)"] -[[package]] -name = "astor" -version = "0.8.1" -description = "Read/rewrite/write Python ASTs" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" -files = [ - {file = "astor-0.8.1-py2.py3-none-any.whl", hash = "sha256:070a54e890cefb5b3739d19f30f5a5ec840ffc9c50ffa7d23cc9fc1a38ebbfc5"}, - {file = "astor-0.8.1.tar.gz", hash = "sha256:6a6effda93f4e1ce9f618779b2dd1d9d84f1e32812c23a29b3fff6fd7f63fa5e"}, -] - [[package]] name = "attrs" version = "24.3.0" @@ -63,18 +52,6 @@ docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphi tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] -[[package]] -name = "autorepr" -version = "0.3.0" -description = "Makes civilized __repr__, __str__, and __unicode__ methods" -optional = false -python-versions = "*" -files = [ - {file = "autorepr-0.3.0-py2-none-any.whl", hash = "sha256:c34567e4073630feb52d9c788fc198085e9e9de4817e3b93b7c4c534fc689f11"}, - {file = "autorepr-0.3.0-py2.py3-none-any.whl", hash = "sha256:1d9010d14fb325d3961e3aa73692685563f97d6ba4a2f0f735329fb37422599c"}, - {file = "autorepr-0.3.0.tar.gz", hash = "sha256:ef770b84793d5433e6bb893054973b8c7ce6b487274f9c3f734f678cae11e85e"}, -] - [[package]] name = "babel" version = "2.16.0" @@ -89,30 +66,6 @@ files = [ [package.extras] dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] -[[package]] -name = "bandit" -version = "1.8.0" -description = "Security oriented static analyser for python code." -optional = false -python-versions = ">=3.9" -files = [ - {file = "bandit-1.8.0-py3-none-any.whl", hash = "sha256:b1a61d829c0968aed625381e426aa378904b996529d048f8d908fa28f6b13e38"}, - {file = "bandit-1.8.0.tar.gz", hash = "sha256:b5bfe55a095abd9fe20099178a7c6c060f844bfd4fe4c76d28e35e4c52b9d31e"}, -] - -[package.dependencies] -colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""} -PyYAML = ">=5.3.1" -rich = "*" -stevedore = ">=1.20.0" - -[package.extras] -baseline = ["GitPython (>=3.1.30)"] -sarif = ["jschema-to-python (>=1.2.3)", "sarif-om (>=1.0.4)"] -test = ["beautifulsoup4 (>=4.8.0)", "coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "pylint (==1.9.4)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)"] -toml = ["tomli (>=1.1.0)"] -yaml = ["PyYAML"] - [[package]] name = "beautifulsoup4" version = "4.12.3" @@ -134,32 +87,6 @@ charset-normalizer = ["charset-normalizer"] html5lib = ["html5lib"] lxml = ["lxml"] -[[package]] -name = "cattrs" -version = "24.1.2" -description = "Composable complex class support for attrs and dataclasses." -optional = false -python-versions = ">=3.8" -files = [ - {file = "cattrs-24.1.2-py3-none-any.whl", hash = "sha256:67c7495b760168d931a10233f979b28dc04daf853b30752246f4f8471c6d68d0"}, - {file = "cattrs-24.1.2.tar.gz", hash = "sha256:8028cfe1ff5382df59dd36474a86e02d817b06eaf8af84555441bac915d2ef85"}, -] - -[package.dependencies] -attrs = ">=23.1.0" -exceptiongroup = {version = ">=1.1.1", markers = "python_version < \"3.11\""} -typing-extensions = {version = ">=4.1.0,<4.6.3 || >4.6.3", markers = "python_version < \"3.11\""} - -[package.extras] -bson = ["pymongo (>=4.4.0)"] -cbor2 = ["cbor2 (>=5.4.6)"] -msgpack = ["msgpack (>=1.0.5)"] -msgspec = ["msgspec (>=0.18.5)"] -orjson = ["orjson (>=3.9.2)"] -pyyaml = ["pyyaml (>=6.0)"] -tomlkit = ["tomlkit (>=0.11.8)"] -ujson = ["ujson (>=5.7.0)"] - [[package]] name = "certifi" version = "2024.12.14" @@ -394,18 +321,18 @@ files = [ ] [[package]] -name = "configupdater" -version = "3.2" -description = "Parser like ConfigParser but for updating configuration files" +name = "covdefaults" +version = "2.3.0" +description = "A coverage plugin to provide sensible default settings" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "ConfigUpdater-3.2-py2.py3-none-any.whl", hash = "sha256:0f65a041627d7693840b4dd743581db4c441c97195298a29d075f91b79539df2"}, - {file = "ConfigUpdater-3.2.tar.gz", hash = "sha256:9fdac53831c1b062929bf398b649b87ca30e7f1a735f3fbf482072804106306b"}, + {file = "covdefaults-2.3.0-py2.py3-none-any.whl", hash = "sha256:2832961f6ffcfe4b57c338bc3418a3526f495c26fb9c54565409c5532f7c41be"}, + {file = "covdefaults-2.3.0.tar.gz", hash = "sha256:4e99f679f12d792bc62e5510fa3eb59546ed47bd569e36e4fddc4081c9c3ebf7"}, ] -[package.extras] -testing = ["flake8", "pytest", "pytest-cov", "pytest-randomly", "pytest-xdist", "sphinx"] +[package.dependencies] +coverage = ">=6.0.2" [[package]] name = "coverage" @@ -484,17 +411,6 @@ tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.1 [package.extras] toml = ["tomli"] -[[package]] -name = "darglint" -version = "1.8.1" -description = "A utility for ensuring Google-style docstrings stay up to date with the source code." -optional = false -python-versions = ">=3.6,<4.0" -files = [ - {file = "darglint-1.8.1-py3-none-any.whl", hash = "sha256:5ae11c259c17b0701618a20c3da343a3eb98b3bc4b5a83d31cdd94f5ebdced8d"}, - {file = "darglint-1.8.1.tar.gz", hash = "sha256:080d5106df149b199822e7ee7deb9c012b49891538f14a11be681044f0bb20da"}, -] - [[package]] name = "decorator" version = "5.1.1" @@ -506,23 +422,6 @@ files = [ {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, ] -[[package]] -name = "dictdiffer" -version = "0.9.0" -description = "Dictdiffer is a library that helps you to diff and patch dictionaries." -optional = false -python-versions = "*" -files = [ - {file = "dictdiffer-0.9.0-py2.py3-none-any.whl", hash = "sha256:442bfc693cfcadaf46674575d2eba1c53b42f5e404218ca2c2ff549f2df56595"}, - {file = "dictdiffer-0.9.0.tar.gz", hash = "sha256:17bacf5fbfe613ccf1b6d512bd766e6b21fb798822a133aa86098b8ac9997578"}, -] - -[package.extras] -all = ["Sphinx (>=3)", "check-manifest (>=0.42)", "mock (>=1.3.0)", "numpy (>=1.13.0)", "numpy (>=1.15.0)", "numpy (>=1.18.0)", "numpy (>=1.20.0)", "pytest (==5.4.3)", "pytest (>=6)", "pytest-cov (>=2.10.1)", "pytest-isort (>=1.2.0)", "pytest-pycodestyle (>=2)", "pytest-pycodestyle (>=2.2.0)", "pytest-pydocstyle (>=2)", "pytest-pydocstyle (>=2.2.0)", "sphinx (>=3)", "sphinx-rtd-theme (>=0.2)", "tox (>=3.7.0)"] -docs = ["Sphinx (>=3)", "sphinx-rtd-theme (>=0.2)"] -numpy = ["numpy (>=1.13.0)", "numpy (>=1.15.0)", "numpy (>=1.18.0)", "numpy (>=1.20.0)"] -tests = ["check-manifest (>=0.42)", "mock (>=1.3.0)", "pytest (==5.4.3)", "pytest (>=6)", "pytest-cov (>=2.10.1)", "pytest-isort (>=1.2.0)", "pytest-pycodestyle (>=2)", "pytest-pycodestyle (>=2.2.0)", "pytest-pydocstyle (>=2)", "pytest-pydocstyle (>=2.2.0)", "sphinx (>=3)", "tox (>=3.7.0)"] - [[package]] name = "docutils" version = "0.21.2" @@ -534,28 +433,6 @@ files = [ {file = "docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f"}, ] -[[package]] -name = "dpath" -version = "2.2.0" -description = "Filesystem-like pathing and searching for dictionaries" -optional = false -python-versions = ">=3.7" -files = [ - {file = "dpath-2.2.0-py3-none-any.whl", hash = "sha256:b330a375ded0a0d2ed404440f6c6a715deae5313af40bbb01c8a41d891900576"}, - {file = "dpath-2.2.0.tar.gz", hash = "sha256:34f7e630dc55ea3f219e555726f5da4b4b25f2200319c8e6902c394258dd6a3e"}, -] - -[[package]] -name = "eradicate" -version = "2.3.0" -description = "Removes commented-out code." -optional = false -python-versions = "*" -files = [ - {file = "eradicate-2.3.0-py3-none-any.whl", hash = "sha256:2b29b3dd27171f209e4ddd8204b70c02f0682ae95eecb353f10e8d72b149c63e"}, - {file = "eradicate-2.3.0.tar.gz", hash = "sha256:06df115be3b87d0fc1c483db22a2ebb12bcf40585722810d809cc770f5031c37"}, -] - [[package]] name = "exceptiongroup" version = "1.2.2" @@ -586,264 +463,6 @@ mccabe = ">=0.7.0,<0.8.0" pycodestyle = ">=2.12.0,<2.13.0" pyflakes = ">=3.2.0,<3.3.0" -[[package]] -name = "flake8-bandit" -version = "4.1.1" -description = "Automated security testing with bandit and flake8." -optional = false -python-versions = ">=3.6" -files = [ - {file = "flake8_bandit-4.1.1-py3-none-any.whl", hash = "sha256:4c8a53eb48f23d4ef1e59293657181a3c989d0077c9952717e98a0eace43e06d"}, - {file = "flake8_bandit-4.1.1.tar.gz", hash = "sha256:068e09287189cbfd7f986e92605adea2067630b75380c6b5733dab7d87f9a84e"}, -] - -[package.dependencies] -bandit = ">=1.7.3" -flake8 = ">=5.0.0" - -[[package]] -name = "flake8-broken-line" -version = "1.0.0" -description = "Flake8 plugin to forbid backslashes for line breaks" -optional = false -python-versions = ">=3.8,<4.0" -files = [ - {file = "flake8_broken_line-1.0.0-py3-none-any.whl", hash = "sha256:96c964336024a5030dc536a9f6fb02aa679e2d2a6b35b80a558b5136c35832a9"}, - {file = "flake8_broken_line-1.0.0.tar.gz", hash = "sha256:e2c6a17f8d9a129e99c1320fce89b33843e2963871025c4c2bb7b8b8d8732a85"}, -] - -[package.dependencies] -flake8 = ">5" - -[[package]] -name = "flake8-bugbear" -version = "24.12.12" -description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." -optional = false -python-versions = ">=3.8.1" -files = [ - {file = "flake8_bugbear-24.12.12-py3-none-any.whl", hash = "sha256:1b6967436f65ca22a42e5373aaa6f2d87966ade9aa38d4baf2a1be550767545e"}, - {file = "flake8_bugbear-24.12.12.tar.gz", hash = "sha256:46273cef0a6b6ff48ca2d69e472f41420a42a46e24b2a8972e4f0d6733d12a64"}, -] - -[package.dependencies] -attrs = ">=22.2.0" -flake8 = ">=6.0.0" - -[package.extras] -dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit", "pytest", "tox"] - -[[package]] -name = "flake8-commas" -version = "2.1.0" -description = "Flake8 lint for trailing commas." -optional = false -python-versions = "*" -files = [ - {file = "flake8-commas-2.1.0.tar.gz", hash = "sha256:940441ab8ee544df564ae3b3f49f20462d75d5c7cac2463e0b27436e2050f263"}, - {file = "flake8_commas-2.1.0-py2.py3-none-any.whl", hash = "sha256:ebb96c31e01d0ef1d0685a21f3f0e2f8153a0381430e748bf0bbbb5d5b453d54"}, -] - -[package.dependencies] -flake8 = ">=2" - -[[package]] -name = "flake8-comprehensions" -version = "3.16.0" -description = "A flake8 plugin to help you write better list/set/dict comprehensions." -optional = false -python-versions = ">=3.9" -files = [ - {file = "flake8_comprehensions-3.16.0-py3-none-any.whl", hash = "sha256:7c1eadc9d22e765f39857798febe7766b4d9c519793c6c149e3e13bf99693f70"}, - {file = "flake8_comprehensions-3.16.0.tar.gz", hash = "sha256:9cbf789905a8f03f9d350fb82b17b264d9a16c7ce3542b2a7b871ef568cafabe"}, -] - -[package.dependencies] -flake8 = ">=3,<3.2 || >3.2" - -[[package]] -name = "flake8-debugger" -version = "4.1.2" -description = "ipdb/pdb statement checker plugin for flake8" -optional = false -python-versions = ">=3.7" -files = [ - {file = "flake8-debugger-4.1.2.tar.gz", hash = "sha256:52b002560941e36d9bf806fca2523dc7fb8560a295d5f1a6e15ac2ded7a73840"}, - {file = "flake8_debugger-4.1.2-py3-none-any.whl", hash = "sha256:0a5e55aeddcc81da631ad9c8c366e7318998f83ff00985a49e6b3ecf61e571bf"}, -] - -[package.dependencies] -flake8 = ">=3.0" -pycodestyle = "*" - -[[package]] -name = "flake8-docstrings" -version = "1.7.0" -description = "Extension for flake8 which uses pydocstyle to check docstrings" -optional = false -python-versions = ">=3.7" -files = [ - {file = "flake8_docstrings-1.7.0-py2.py3-none-any.whl", hash = "sha256:51f2344026da083fc084166a9353f5082b01f72901df422f74b4d953ae88ac75"}, - {file = "flake8_docstrings-1.7.0.tar.gz", hash = "sha256:4c8cc748dc16e6869728699e5d0d685da9a10b0ea718e090b1ba088e67a941af"}, -] - -[package.dependencies] -flake8 = ">=3" -pydocstyle = ">=2.1" - -[[package]] -name = "flake8-eradicate" -version = "1.5.0" -description = "Flake8 plugin to find commented out code" -optional = false -python-versions = ">=3.8,<4.0" -files = [ - {file = "flake8_eradicate-1.5.0-py3-none-any.whl", hash = "sha256:18acc922ad7de623f5247c7d5595da068525ec5437dd53b22ec2259b96ce9d22"}, - {file = "flake8_eradicate-1.5.0.tar.gz", hash = "sha256:aee636cb9ecb5594a7cd92d67ad73eb69909e5cc7bd81710cf9d00970f3983a6"}, -] - -[package.dependencies] -attrs = "*" -eradicate = ">=2.0,<3.0" -flake8 = ">5" - -[[package]] -name = "flake8-isort" -version = "6.1.1" -description = "flake8 plugin that integrates isort" -optional = false -python-versions = ">=3.8" -files = [ - {file = "flake8_isort-6.1.1-py3-none-any.whl", hash = "sha256:0fec4dc3a15aefbdbe4012e51d5531a2eb5fa8b981cdfbc882296a59b54ede12"}, - {file = "flake8_isort-6.1.1.tar.gz", hash = "sha256:c1f82f3cf06a80c13e1d09bfae460e9666255d5c780b859f19f8318d420370b3"}, -] - -[package.dependencies] -flake8 = "*" -isort = ">=5.0.0,<6" - -[package.extras] -test = ["pytest"] - -[[package]] -name = "flake8-plugin-utils" -version = "1.3.3" -description = "The package provides base classes and utils for flake8 plugin writing" -optional = false -python-versions = ">=3.6,<4.0" -files = [ - {file = "flake8-plugin-utils-1.3.3.tar.gz", hash = "sha256:39f6f338d038b301c6fd344b06f2e81e382b68fa03c0560dff0d9b1791a11a2c"}, - {file = "flake8_plugin_utils-1.3.3-py3-none-any.whl", hash = "sha256:e4848c57d9d50f19100c2d75fa794b72df068666a9041b4b0409be923356a3ed"}, -] - -[[package]] -name = "flake8-pyi" -version = "24.9.0" -description = "A plugin for flake8 to enable linting .pyi stub files." -optional = false -python-versions = ">=3.9" -files = [ - {file = "flake8_pyi-24.9.0-py3-none-any.whl", hash = "sha256:c199b21e5a00b509d337bf376310437f16987e03bff4b1055d8b579d7bb3c01a"}, - {file = "flake8_pyi-24.9.0.tar.gz", hash = "sha256:64fb735022958147afedd52781f263de337a34d118f3294ab2deb184f1c20cd9"}, -] - -[package.dependencies] -flake8 = ">=6.0.0,<8.0.0" -pyflakes = ">=2.1.1" - -[package.extras] -dev = ["black (==24.8.0)", "flake8-bugbear (==24.8.19)", "flake8-noqa (==1.4.0)", "isort (==5.13.2)", "mypy (==1.11.2)", "pre-commit-hooks (==4.6.0)", "pytest (==8.3.3)", "pytest-xdist (==3.6.1)", "types-pyflakes (<4)"] - -[[package]] -name = "flake8-pytest-style" -version = "2.0.0" -description = "A flake8 plugin checking common style issues or inconsistencies with pytest-based tests." -optional = false -python-versions = "<4.0.0,>=3.8.1" -files = [ - {file = "flake8_pytest_style-2.0.0-py3-none-any.whl", hash = "sha256:abcb9f56f277954014b749e5a0937fae215be01a21852e9d05e7600c3de6aae5"}, - {file = "flake8_pytest_style-2.0.0.tar.gz", hash = "sha256:919c328cacd4bc4f873ea61ab4db0d8f2c32e0db09a3c73ab46b1de497556464"}, -] - -[package.dependencies] -flake8-plugin-utils = ">=1.3.2,<2.0.0" - -[[package]] -name = "flake8-quotes" -version = "3.4.0" -description = "Flake8 lint for quotes." -optional = false -python-versions = "*" -files = [ - {file = "flake8-quotes-3.4.0.tar.gz", hash = "sha256:aad8492fb710a2d3eabe68c5f86a1428de650c8484127e14c43d0504ba30276c"}, -] - -[package.dependencies] -flake8 = "*" -setuptools = "*" - -[[package]] -name = "flake8-rst-docstrings" -version = "0.3.0" -description = "Python docstring reStructuredText (RST) validator for flake8" -optional = false -python-versions = ">=3.7" -files = [ - {file = "flake8-rst-docstrings-0.3.0.tar.gz", hash = "sha256:d1ce22b4bd37b73cd86b8d980e946ef198cfcc18ed82fedb674ceaa2f8d1afa4"}, - {file = "flake8_rst_docstrings-0.3.0-py3-none-any.whl", hash = "sha256:f8c3c6892ff402292651c31983a38da082480ad3ba253743de52989bdc84ca1c"}, -] - -[package.dependencies] -flake8 = ">=3" -pygments = "*" -restructuredtext-lint = "*" - -[package.extras] -develop = ["build", "twine"] - -[[package]] -name = "flake8-string-format" -version = "0.3.0" -description = "string format checker, plugin for flake8" -optional = false -python-versions = "*" -files = [ - {file = "flake8-string-format-0.3.0.tar.gz", hash = "sha256:65f3da786a1461ef77fca3780b314edb2853c377f2e35069723348c8917deaa2"}, - {file = "flake8_string_format-0.3.0-py2.py3-none-any.whl", hash = "sha256:812ff431f10576a74c89be4e85b8e075a705be39bc40c4b4278b5b13e2afa9af"}, -] - -[package.dependencies] -flake8 = "*" - -[[package]] -name = "flatten-dict" -version = "0.4.2" -description = "A flexible utility for flattening and unflattening dict-like objects in Python." -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -files = [ - {file = "flatten-dict-0.4.2.tar.gz", hash = "sha256:506a96b6e6f805b81ae46a0f9f31290beb5fa79ded9d80dbe1b7fa236ab43076"}, - {file = "flatten_dict-0.4.2-py2.py3-none-any.whl", hash = "sha256:7e245b20c4c718981212210eec4284a330c9f713e632e98765560e05421e48ad"}, -] - -[package.dependencies] -six = ">=1.12,<2.0" - -[[package]] -name = "furl" -version = "2.1.3" -description = "URL manipulation made simple." -optional = false -python-versions = "*" -files = [ - {file = "furl-2.1.3-py2.py3-none-any.whl", hash = "sha256:9ab425062c4217f9802508e45feb4a83e54324273ac4b202f1850363309666c0"}, - {file = "furl-2.1.3.tar.gz", hash = "sha256:5a6188fe2666c484a12159c18be97a1977a71d632ef5bb867ef15f54af39cc4e"}, -] - -[package.dependencies] -orderedmultidict = ">=1.0.1" -six = ">=1.8.0" - [[package]] name = "furo" version = "2024.8.6" @@ -861,16 +480,6 @@ pygments = ">=2.7" sphinx = ">=6.0,<9.0" sphinx-basic-ng = ">=1.0.0.beta2" -[[package]] -name = "gitignore-parser" -version = "0.1.11" -description = "A spec-compliant gitignore parser for Python 3.5+" -optional = false -python-versions = "*" -files = [ - {file = "gitignore_parser-0.1.11.tar.gz", hash = "sha256:fa10fde48b44888eeefac096f53bcdad9b87a4ffd7db788558dbdf71ff3bc9db"}, -] - [[package]] name = "h11" version = "0.14.0" @@ -929,13 +538,13 @@ zstd = ["zstandard (>=0.18.0)"] [[package]] name = "hypothesis" -version = "6.123.1" +version = "6.123.2" description = "A library for property-based testing" optional = true python-versions = ">=3.9" files = [ - {file = "hypothesis-6.123.1-py3-none-any.whl", hash = "sha256:acf177faeff578f02afef2744c00b9ec3ce03f3b72ffbb6d7013f7baeebaac5e"}, - {file = "hypothesis-6.123.1.tar.gz", hash = "sha256:eb2bf646537ad818270feff6428c34f57813a4ef78781861ec1693b0840ab1d8"}, + {file = "hypothesis-6.123.2-py3-none-any.whl", hash = "sha256:0a8bf07753f1436f1b8697a13ea955f3fef3ef7b477c2972869b1d142bcdb30e"}, + {file = "hypothesis-6.123.2.tar.gz", hash = "sha256:02c25552783764146b191c69eef69d8375827b58a75074055705ab8fdbc95fc5"}, ] [package.dependencies] @@ -960,20 +569,6 @@ pytz = ["pytz (>=2014.1)"] redis = ["redis (>=3.0.0)"] zoneinfo = ["tzdata (>=2024.2)"] -[[package]] -name = "identify" -version = "2.6.3" -description = "File identification library for Python" -optional = false -python-versions = ">=3.9" -files = [ - {file = "identify-2.6.3-py2.py3-none-any.whl", hash = "sha256:9edba65473324c2ea9684b1f944fe3191db3345e50b6d04571d10ed164f8d7bd"}, - {file = "identify-2.6.3.tar.gz", hash = "sha256:62f5dae9b5fef52c84cc188514e9ea4f3f636b1d8799ab5ebc475471f9e47a02"}, -] - -[package.extras] -license = ["ukkonen"] - [[package]] name = "idna" version = "3.10" @@ -1010,20 +605,6 @@ files = [ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] -[[package]] -name = "isort" -version = "5.13.2" -description = "A Python utility / library to sort Python imports." -optional = false -python-versions = ">=3.8.0" -files = [ - {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, - {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, -] - -[package.extras] -colors = ["colorama (>=0.4.6)"] - [[package]] name = "jinja2" version = "3.1.5" @@ -1041,17 +622,6 @@ MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] -[[package]] -name = "jmespath" -version = "1.0.1" -description = "JSON Matching Expressions" -optional = false -python-versions = ">=3.7" -files = [ - {file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"}, - {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"}, -] - [[package]] name = "jsonschema" version = "4.23.0" @@ -1087,24 +657,6 @@ files = [ [package.dependencies] referencing = ">=0.31.0" -[[package]] -name = "loguru" -version = "0.7.3" -description = "Python logging made (stupidly) simple" -optional = false -python-versions = "<4.0,>=3.5" -files = [ - {file = "loguru-0.7.3-py3-none-any.whl", hash = "sha256:31a33c10c8e1e10422bfd431aeb5d351c7cf7fa671e3c4df004162264b28220c"}, - {file = "loguru-0.7.3.tar.gz", hash = "sha256:19480589e77d47b8d85b2c827ad95d49bf31b0dcde16593892eb51dd18706eb6"}, -] - -[package.dependencies] -colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""} -win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} - -[package.extras] -dev = ["Sphinx (==8.1.3)", "build (==1.2.2)", "colorama (==0.4.5)", "colorama (==0.4.6)", "exceptiongroup (==1.1.3)", "freezegun (==1.1.0)", "freezegun (==1.5.0)", "mypy (==v0.910)", "mypy (==v0.971)", "mypy (==v1.13.0)", "mypy (==v1.4.1)", "myst-parser (==4.0.0)", "pre-commit (==4.0.1)", "pytest (==6.1.2)", "pytest (==8.3.2)", "pytest-cov (==2.12.1)", "pytest-cov (==5.0.0)", "pytest-cov (==6.0.0)", "pytest-mypy-plugins (==1.9.3)", "pytest-mypy-plugins (==3.1.0)", "sphinx-rtd-theme (==3.0.2)", "tox (==3.27.1)", "tox (==4.23.2)", "twine (==6.0.1)"] - [[package]] name = "markdown-it-py" version = "3.0.0" @@ -1199,38 +751,6 @@ files = [ {file = "markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0"}, ] -[[package]] -name = "marshmallow" -version = "3.23.2" -description = "A lightweight library for converting complex datatypes to and from native Python datatypes." -optional = false -python-versions = ">=3.9" -files = [ - {file = "marshmallow-3.23.2-py3-none-any.whl", hash = "sha256:bcaf2d6fd74fb1459f8450e85d994997ad3e70036452cbfa4ab685acb19479b3"}, - {file = "marshmallow-3.23.2.tar.gz", hash = "sha256:c448ac6455ca4d794773f00bae22c2f351d62d739929f761dce5eacb5c468d7f"}, -] - -[package.dependencies] -packaging = ">=17.0" - -[package.extras] -dev = ["marshmallow[tests]", "pre-commit (>=3.5,<5.0)", "tox"] -docs = ["alabaster (==1.0.0)", "autodocsumm (==0.2.14)", "sphinx (==8.1.3)", "sphinx-issues (==5.0.0)", "sphinx-version-warning (==1.1.2)"] -tests = ["pytest", "simplejson"] - -[[package]] -name = "marshmallow-polyfield" -version = "5.11" -description = "An unofficial extension to Marshmallow to allow for polymorphic fields" -optional = false -python-versions = ">=3.5" -files = [ - {file = "marshmallow-polyfield-5.11.tar.gz", hash = "sha256:8075a9cc490da4af58b902b4a40a99882dd031adb7aaa96abd147a4fcd53415f"}, -] - -[package.dependencies] -marshmallow = ">=3.0.0b10" - [[package]] name = "mccabe" version = "0.7.0" @@ -1272,17 +792,6 @@ files = [ {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, ] -[[package]] -name = "more-itertools" -version = "10.5.0" -description = "More routines for operating on iterables, beyond itertools" -optional = false -python-versions = ">=3.8" -files = [ - {file = "more-itertools-10.5.0.tar.gz", hash = "sha256:5482bfef7849c25dc3c6dd53a6173ae4795da2a41a80faea6700d9f5846c5da6"}, - {file = "more_itertools-10.5.0-py3-none-any.whl", hash = "sha256:037b0d3203ce90cca8ab1defbbdac29d5f993fc20131f3664dc8d6acfa872aef"}, -] - [[package]] name = "mypy" version = "1.14.0" @@ -1373,64 +882,6 @@ rtd = ["ipython", "sphinx (>=7)", "sphinx-autodoc2 (>=0.5.0,<0.6.0)", "sphinx-bo testing = ["beautifulsoup4", "coverage[toml]", "defusedxml", "pytest (>=8,<9)", "pytest-cov", "pytest-param-files (>=0.6.0,<0.7.0)", "pytest-regressions", "sphinx-pytest"] testing-docutils = ["pygments", "pytest (>=8,<9)", "pytest-param-files (>=0.6.0,<0.7.0)"] -[[package]] -name = "nitpick" -version = "0.35.0" -description = "Enforce the same settings across multiple language-independent projects" -optional = false -python-versions = ">=3.8,<4.0" -files = [ - {file = "nitpick-0.35.0-py3-none-any.whl", hash = "sha256:9911d32c2d488b41914aa1a6d230531fa92bbe3d6610e4a468a5cb5e30fab907"}, - {file = "nitpick-0.35.0.tar.gz", hash = "sha256:098167a4c65655aca52c0ea3876b1e71cf634a27d0e17b971bce9bfcc1f3febe"}, -] - -[package.dependencies] -attrs = ">=20.1.0" -autorepr = "*" -click = "*" -ConfigUpdater = "*" -dictdiffer = "*" -dpath = "*" -flake8 = ">=3.0.0" -flatten-dict = "*" -furl = "*" -gitignore_parser = "*" -identify = "*" -jmespath = "*" -loguru = "*" -marshmallow = ">=3.0.0b10" -marshmallow-polyfield = ">=5.10,<6.0" -more-itertools = "*" -packaging = "*" -pluggy = "*" -python-slugify = "*" -requests = "*" -requests-cache = ">=1.0.0" -"ruamel.yaml" = "*" -sortedcontainers = "*" -StrEnum = "*" -toml = "*" -tomlkit = ">=0.8.0" - -[package.extras] -doc = ["sphinx", "sphinx-gitref", "sphinx_rtd_theme", "sphobjinv"] -lint = ["pylint"] -test = ["freezegun", "pytest", "pytest-cov", "pytest-datadir", "pytest-socket", "pytest-testmon", "pytest-watch", "responses", "testfixtures"] - -[[package]] -name = "orderedmultidict" -version = "1.0.1" -description = "Ordered Multivalue Dictionary" -optional = false -python-versions = "*" -files = [ - {file = "orderedmultidict-1.0.1-py2.py3-none-any.whl", hash = "sha256:43c839a17ee3cdd62234c47deca1a8508a3f2ca1d0678a3bf791c87cf84adbf3"}, - {file = "orderedmultidict-1.0.1.tar.gz", hash = "sha256:04070bbb5e87291cc9bfa51df413677faf2141c73c61d2a5f7b26bea3cd882ad"}, -] - -[package.dependencies] -six = ">=1.8.0" - [[package]] name = "outcome" version = "1.3.0.post0" @@ -1456,47 +907,6 @@ files = [ {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, ] -[[package]] -name = "pbr" -version = "6.1.0" -description = "Python Build Reasonableness" -optional = false -python-versions = ">=2.6" -files = [ - {file = "pbr-6.1.0-py2.py3-none-any.whl", hash = "sha256:a776ae228892d8013649c0aeccbb3d5f99ee15e005a4cbb7e61d55a067b28a2a"}, - {file = "pbr-6.1.0.tar.gz", hash = "sha256:788183e382e3d1d7707db08978239965e8b9e4e5ed42669bf4758186734d5f24"}, -] - -[[package]] -name = "pep8-naming" -version = "0.13.3" -description = "Check PEP-8 naming conventions, plugin for flake8" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pep8-naming-0.13.3.tar.gz", hash = "sha256:1705f046dfcd851378aac3be1cd1551c7c1e5ff363bacad707d43007877fa971"}, - {file = "pep8_naming-0.13.3-py3-none-any.whl", hash = "sha256:1a86b8c71a03337c97181917e2b472f0f5e4ccb06844a0d6f0a33522549e7a80"}, -] - -[package.dependencies] -flake8 = ">=5.0.0" - -[[package]] -name = "platformdirs" -version = "4.3.6" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." -optional = false -python-versions = ">=3.8" -files = [ - {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, - {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, -] - -[package.extras] -docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)"] -type = ["mypy (>=1.11.2)"] - [[package]] name = "pluggy" version = "1.5.0" @@ -1534,23 +944,6 @@ files = [ {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, ] -[[package]] -name = "pydocstyle" -version = "6.3.0" -description = "Python docstring style checker" -optional = false -python-versions = ">=3.6" -files = [ - {file = "pydocstyle-6.3.0-py3-none-any.whl", hash = "sha256:118762d452a49d6b05e194ef344a55822987a462831ade91ec5c06fd2169d019"}, - {file = "pydocstyle-6.3.0.tar.gz", hash = "sha256:7ce43f0c0ac87b07494eb9c0b462c0b73e6ff276807f204d6b53edc72b7e44e1"}, -] - -[package.dependencies] -snowballstemmer = ">=2.2.0" - -[package.extras] -toml = ["tomli (>=1.2.3)"] - [[package]] name = "pyflakes" version = "3.2.0" @@ -1681,23 +1074,6 @@ files = [ attrs = ">=19.2.0" pytest = ">=7.4" -[[package]] -name = "python-slugify" -version = "8.0.4" -description = "A Python slugify application that also handles Unicode" -optional = false -python-versions = ">=3.7" -files = [ - {file = "python-slugify-8.0.4.tar.gz", hash = "sha256:59202371d1d05b54a9e7720c5e038f928f45daaffe41dd10822f3907b937c856"}, - {file = "python_slugify-8.0.4-py2.py3-none-any.whl", hash = "sha256:276540b79961052b66b7d116620b36518847f52d5fd9e3a70164fc8c50faa6b8"}, -] - -[package.dependencies] -text-unidecode = ">=1.3" - -[package.extras] -unidecode = ["Unidecode (>=1.1.1)"] - [[package]] name = "pyyaml" version = "6.0.2" @@ -1899,68 +1275,6 @@ urllib3 = ">=1.21.1,<3" socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] -[[package]] -name = "requests-cache" -version = "1.2.1" -description = "A persistent cache for python requests" -optional = false -python-versions = ">=3.8" -files = [ - {file = "requests_cache-1.2.1-py3-none-any.whl", hash = "sha256:1285151cddf5331067baa82598afe2d47c7495a1334bfe7a7d329b43e9fd3603"}, - {file = "requests_cache-1.2.1.tar.gz", hash = "sha256:68abc986fdc5b8d0911318fbb5f7c80eebcd4d01bfacc6685ecf8876052511d1"}, -] - -[package.dependencies] -attrs = ">=21.2" -cattrs = ">=22.2" -platformdirs = ">=2.5" -requests = ">=2.22" -url-normalize = ">=1.4" -urllib3 = ">=1.25.5" - -[package.extras] -all = ["boto3 (>=1.15)", "botocore (>=1.18)", "itsdangerous (>=2.0)", "pymongo (>=3)", "pyyaml (>=6.0.1)", "redis (>=3)", "ujson (>=5.4)"] -bson = ["bson (>=0.5)"] -docs = ["furo (>=2023.3,<2024.0)", "linkify-it-py (>=2.0,<3.0)", "myst-parser (>=1.0,<2.0)", "sphinx (>=5.0.2,<6.0.0)", "sphinx-autodoc-typehints (>=1.19)", "sphinx-automodapi (>=0.14)", "sphinx-copybutton (>=0.5)", "sphinx-design (>=0.2)", "sphinx-notfound-page (>=0.8)", "sphinxcontrib-apidoc (>=0.3)", "sphinxext-opengraph (>=0.9)"] -dynamodb = ["boto3 (>=1.15)", "botocore (>=1.18)"] -json = ["ujson (>=5.4)"] -mongodb = ["pymongo (>=3)"] -redis = ["redis (>=3)"] -security = ["itsdangerous (>=2.0)"] -yaml = ["pyyaml (>=6.0.1)"] - -[[package]] -name = "restructuredtext-lint" -version = "1.4.0" -description = "reStructuredText linter" -optional = false -python-versions = "*" -files = [ - {file = "restructuredtext_lint-1.4.0.tar.gz", hash = "sha256:1b235c0c922341ab6c530390892eb9e92f90b9b75046063e047cacfb0f050c45"}, -] - -[package.dependencies] -docutils = ">=0.11,<1.0" - -[[package]] -name = "rich" -version = "13.9.4" -description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" -optional = false -python-versions = ">=3.8.0" -files = [ - {file = "rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90"}, - {file = "rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098"}, -] - -[package.dependencies] -markdown-it-py = ">=2.2.0" -pygments = ">=2.13.0,<3.0.0" -typing-extensions = {version = ">=4.0.0,<5.0", markers = "python_version < \"3.11\""} - -[package.extras] -jupyter = ["ipywidgets (>=7.5.1,<9)"] - [[package]] name = "rpds-py" version = "0.22.3" @@ -2074,102 +1388,30 @@ files = [ ] [[package]] -name = "ruamel-yaml" -version = "0.18.6" -description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" +name = "ruff" +version = "0.8.4" +description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruamel.yaml-0.18.6-py3-none-any.whl", hash = "sha256:57b53ba33def16c4f3d807c0ccbc00f8a6081827e81ba2491691b76882d0c636"}, - {file = "ruamel.yaml-0.18.6.tar.gz", hash = "sha256:8b27e6a217e786c6fbe5634d8f3f11bc63e0f80f6a5890f28863d9c45aac311b"}, -] - -[package.dependencies] -"ruamel.yaml.clib" = {version = ">=0.2.7", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.13\""} - -[package.extras] -docs = ["mercurial (>5.7)", "ryd"] -jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] - -[[package]] -name = "ruamel-yaml-clib" -version = "0.2.12" -description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" -optional = false -python-versions = ">=3.9" -files = [ - {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:11f891336688faf5156a36293a9c362bdc7c88f03a8a027c2c1d8e0bcde998e5"}, - {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:a606ef75a60ecf3d924613892cc603b154178ee25abb3055db5062da811fd969"}, - {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd5415dded15c3822597455bc02bcd66e81ef8b7a48cb71a33628fc9fdde39df"}, - {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f66efbc1caa63c088dead1c4170d148eabc9b80d95fb75b6c92ac0aad2437d76"}, - {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:22353049ba4181685023b25b5b51a574bce33e7f51c759371a7422dcae5402a6"}, - {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:932205970b9f9991b34f55136be327501903f7c66830e9760a8ffb15b07f05cd"}, - {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-win32.whl", hash = "sha256:3eac5a91891ceb88138c113f9db04f3cebdae277f5d44eaa3651a4f573e6a5da"}, - {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-win_amd64.whl", hash = "sha256:ab007f2f5a87bd08ab1499bdf96f3d5c6ad4dcfa364884cb4549aa0154b13a28"}, - {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:4a6679521a58256a90b0d89e03992c15144c5f3858f40d7c18886023d7943db6"}, - {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:d84318609196d6bd6da0edfa25cedfbabd8dbde5140a0a23af29ad4b8f91fb1e"}, - {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb43a269eb827806502c7c8efb7ae7e9e9d0573257a46e8e952f4d4caba4f31e"}, - {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:811ea1594b8a0fb466172c384267a4e5e367298af6b228931f273b111f17ef52"}, - {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cf12567a7b565cbf65d438dec6cfbe2917d3c1bdddfce84a9930b7d35ea59642"}, - {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7dd5adc8b930b12c8fc5b99e2d535a09889941aa0d0bd06f4749e9a9397c71d2"}, - {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-win32.whl", hash = "sha256:bd0a08f0bab19093c54e18a14a10b4322e1eacc5217056f3c063bd2f59853ce4"}, - {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-win_amd64.whl", hash = "sha256:a274fb2cb086c7a3dea4322ec27f4cb5cc4b6298adb583ab0e211a4682f241eb"}, - {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:20b0f8dc160ba83b6dcc0e256846e1a02d044e13f7ea74a3d1d56ede4e48c632"}, - {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:943f32bc9dedb3abff9879edc134901df92cfce2c3d5c9348f172f62eb2d771d"}, - {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95c3829bb364fdb8e0332c9931ecf57d9be3519241323c5274bd82f709cebc0c"}, - {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:749c16fcc4a2b09f28843cda5a193e0283e47454b63ec4b81eaa2242f50e4ccd"}, - {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bf165fef1f223beae7333275156ab2022cffe255dcc51c27f066b4370da81e31"}, - {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:32621c177bbf782ca5a18ba4d7af0f1082a3f6e517ac2a18b3974d4edf349680"}, - {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-win32.whl", hash = "sha256:e8c4ebfcfd57177b572e2040777b8abc537cdef58a2120e830124946aa9b42c5"}, - {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-win_amd64.whl", hash = "sha256:0467c5965282c62203273b838ae77c0d29d7638c8a4e3a1c8bdd3602c10904e4"}, - {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:4c8c5d82f50bb53986a5e02d1b3092b03622c02c2eb78e29bec33fd9593bae1a"}, - {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux2014_aarch64.whl", hash = "sha256:e7e3736715fbf53e9be2a79eb4db68e4ed857017344d697e8b9749444ae57475"}, - {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b7e75b4965e1d4690e93021adfcecccbca7d61c7bddd8e22406ef2ff20d74ef"}, - {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96777d473c05ee3e5e3c3e999f5d23c6f4ec5b0c38c098b3a5229085f74236c6"}, - {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:3bc2a80e6420ca8b7d3590791e2dfc709c88ab9152c00eeb511c9875ce5778bf"}, - {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:e188d2699864c11c36cdfdada94d781fd5d6b0071cd9c427bceb08ad3d7c70e1"}, - {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-win32.whl", hash = "sha256:6442cb36270b3afb1b4951f060eccca1ce49f3d087ca1ca4563a6eb479cb3de6"}, - {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-win_amd64.whl", hash = "sha256:e5b8daf27af0b90da7bb903a876477a9e6d7270be6146906b276605997c7e9a3"}, - {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:fc4b630cd3fa2cf7fce38afa91d7cfe844a9f75d7f0f36393fa98815e911d987"}, - {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:bc5f1e1c28e966d61d2519f2a3d451ba989f9ea0f2307de7bc45baa526de9e45"}, - {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a0e060aace4c24dcaf71023bbd7d42674e3b230f7e7b97317baf1e953e5b519"}, - {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2f1c3765db32be59d18ab3953f43ab62a761327aafc1594a2a1fbe038b8b8a7"}, - {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d85252669dc32f98ebcd5d36768f5d4faeaeaa2d655ac0473be490ecdae3c285"}, - {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e143ada795c341b56de9418c58d028989093ee611aa27ffb9b7f609c00d813ed"}, - {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-win32.whl", hash = "sha256:beffaed67936fbbeffd10966a4eb53c402fafd3d6833770516bf7314bc6ffa12"}, - {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-win_amd64.whl", hash = "sha256:040ae85536960525ea62868b642bdb0c2cc6021c9f9d507810c0c604e66f5a7b"}, - {file = "ruamel.yaml.clib-0.2.12.tar.gz", hash = "sha256:6c8fbb13ec503f99a91901ab46e0b07ae7941cd527393187039aec586fdfd36f"}, -] - -[[package]] -name = "setuptools" -version = "75.6.0" -description = "Easily download, build, install, upgrade, and uninstall Python packages" -optional = false -python-versions = ">=3.9" -files = [ - {file = "setuptools-75.6.0-py3-none-any.whl", hash = "sha256:ce74b49e8f7110f9bf04883b730f4765b774ef3ef28f722cce7c273d253aaf7d"}, - {file = "setuptools-75.6.0.tar.gz", hash = "sha256:8199222558df7c86216af4f84c30e9b34a61d8ba19366cc914424cdbd28252f6"}, -] - -[package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.7.0)"] -core = ["importlib_metadata (>=6)", "jaraco.collections", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] -cover = ["pytest-cov"] -doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] -enabler = ["pytest-enabler (>=2.2)"] -test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] -type = ["importlib_metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (>=1.12,<1.14)", "pytest-mypy"] - -[[package]] -name = "six" -version = "1.17.0" -description = "Python 2 and 3 compatibility utilities" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -files = [ - {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, - {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, + {file = "ruff-0.8.4-py3-none-linux_armv6l.whl", hash = "sha256:58072f0c06080276804c6a4e21a9045a706584a958e644353603d36ca1eb8a60"}, + {file = "ruff-0.8.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ffb60904651c00a1e0b8df594591770018a0f04587f7deeb3838344fe3adabac"}, + {file = "ruff-0.8.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:6ddf5d654ac0d44389f6bf05cee4caeefc3132a64b58ea46738111d687352296"}, + {file = "ruff-0.8.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e248b1f0fa2749edd3350a2a342b67b43a2627434c059a063418e3d375cfe643"}, + {file = "ruff-0.8.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bf197b98ed86e417412ee3b6c893f44c8864f816451441483253d5ff22c0e81e"}, + {file = "ruff-0.8.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c41319b85faa3aadd4d30cb1cffdd9ac6b89704ff79f7664b853785b48eccdf3"}, + {file = "ruff-0.8.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:9f8402b7c4f96463f135e936d9ab77b65711fcd5d72e5d67597b543bbb43cf3f"}, + {file = "ruff-0.8.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4e56b3baa9c23d324ead112a4fdf20db9a3f8f29eeabff1355114dd96014604"}, + {file = "ruff-0.8.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:736272574e97157f7edbbb43b1d046125fce9e7d8d583d5d65d0c9bf2c15addf"}, + {file = "ruff-0.8.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5fe710ab6061592521f902fca7ebcb9fabd27bc7c57c764298b1c1f15fff720"}, + {file = "ruff-0.8.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:13e9ec6d6b55f6da412d59953d65d66e760d583dd3c1c72bf1f26435b5bfdbae"}, + {file = "ruff-0.8.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:97d9aefef725348ad77d6db98b726cfdb075a40b936c7984088804dfd38268a7"}, + {file = "ruff-0.8.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:ab78e33325a6f5374e04c2ab924a3367d69a0da36f8c9cb6b894a62017506111"}, + {file = "ruff-0.8.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:8ef06f66f4a05c3ddbc9121a8b0cecccd92c5bf3dd43b5472ffe40b8ca10f0f8"}, + {file = "ruff-0.8.4-py3-none-win32.whl", hash = "sha256:552fb6d861320958ca5e15f28b20a3d071aa83b93caee33a87b471f99a6c0835"}, + {file = "ruff-0.8.4-py3-none-win_amd64.whl", hash = "sha256:f21a1143776f8656d7f364bd264a9d60f01b7f52243fbe90e7670c0dfe0cf65d"}, + {file = "ruff-0.8.4-py3-none-win_arm64.whl", hash = "sha256:9183dd615d8df50defa8b1d9a074053891ba39025cf5ae88e8bcb52edcc4bf08"}, + {file = "ruff-0.8.4.tar.gz", hash = "sha256:0d5f89f254836799af1615798caa5f80b7f935d7a670fad66c5007928e57ace8"}, ] [[package]] @@ -2414,58 +1656,6 @@ lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] standalone = ["Sphinx (>=5)"] test = ["pytest"] -[[package]] -name = "stevedore" -version = "5.4.0" -description = "Manage dynamic plugins for Python applications" -optional = false -python-versions = ">=3.9" -files = [ - {file = "stevedore-5.4.0-py3-none-any.whl", hash = "sha256:b0be3c4748b3ea7b854b265dcb4caa891015e442416422be16f8b31756107857"}, - {file = "stevedore-5.4.0.tar.gz", hash = "sha256:79e92235ecb828fe952b6b8b0c6c87863248631922c8e8e0fa5b17b232c4514d"}, -] - -[package.dependencies] -pbr = ">=2.0.0" - -[[package]] -name = "strenum" -version = "0.4.15" -description = "An Enum that inherits from str." -optional = false -python-versions = "*" -files = [ - {file = "StrEnum-0.4.15-py3-none-any.whl", hash = "sha256:a30cda4af7cc6b5bf52c8055bc4bf4b2b6b14a93b574626da33df53cf7740659"}, - {file = "StrEnum-0.4.15.tar.gz", hash = "sha256:878fb5ab705442070e4dd1929bb5e2249511c0bcf2b0eeacf3bcd80875c82eff"}, -] - -[package.extras] -docs = ["myst-parser[linkify]", "sphinx", "sphinx-rtd-theme"] -release = ["twine"] -test = ["pylint", "pytest", "pytest-black", "pytest-cov", "pytest-pylint"] - -[[package]] -name = "text-unidecode" -version = "1.3" -description = "The most basic Text::Unidecode port" -optional = false -python-versions = "*" -files = [ - {file = "text-unidecode-1.3.tar.gz", hash = "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93"}, - {file = "text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8"}, -] - -[[package]] -name = "toml" -version = "0.10.2" -description = "Python Library for Tom's Obvious, Minimal Language" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -files = [ - {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, - {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, -] - [[package]] name = "tomli" version = "2.2.1" @@ -2549,20 +1739,6 @@ files = [ {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, ] -[[package]] -name = "url-normalize" -version = "1.4.3" -description = "URL normalization for Python" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" -files = [ - {file = "url-normalize-1.4.3.tar.gz", hash = "sha256:d23d3a070ac52a67b83a1c59a0e68f8608d1cd538783b401bc9de2c0fac999b2"}, - {file = "url_normalize-1.4.3-py2.py3-none-any.whl", hash = "sha256:ec3c301f04e5bb676d333a7fa162fa977ad2ca04b7e652bfc9fac4e405728eed"}, -] - -[package.dependencies] -six = "*" - [[package]] name = "urllib3" version = "2.3.0" @@ -2582,50 +1758,19 @@ zstd = ["zstandard (>=0.18.0)"] [[package]] name = "wemake-python-styleguide" -version = "0.19.2" +version = "1.0.0" description = "The strictest and most opinionated python linter ever" optional = false -python-versions = "<4.0,>=3.9" +python-versions = "<4.0,>=3.10" files = [ - {file = "wemake_python_styleguide-0.19.2-py3-none-any.whl", hash = "sha256:d53205dbb629755026d853d15fb3ca03ebb2717c97de4198b5676b9bdc0663bd"}, - {file = "wemake_python_styleguide-0.19.2.tar.gz", hash = "sha256:850fe70e6d525fd37ac51778e552a121a489f1bd057184de96ffd74a09aef414"}, + {file = "wemake_python_styleguide-1.0.0-py3-none-any.whl", hash = "sha256:c0cc3fe2a2aa8d7ca76f02bc27bfe344c76ed9652f94859c241b96f0fcefa9ac"}, + {file = "wemake_python_styleguide-1.0.0.tar.gz", hash = "sha256:00e96dc73faf5471b21d4baa5041f457c19739cf14677832429be69e5f4f7964"}, ] [package.dependencies] -astor = ">=0.8,<0.9" attrs = "*" -darglint = ">=1.2,<2.0" -flake8 = ">=7.0,<8.0" -flake8-bandit = ">=4.1,<5.0" -flake8-broken-line = ">=1.0,<2.0" -flake8-bugbear = ">=24.2,<25.0" -flake8-commas = ">=2.0,<3.0" -flake8-comprehensions = ">=3.1,<4.0" -flake8-debugger = ">=4.0,<5.0" -flake8-docstrings = ">=1.3,<2.0" -flake8-eradicate = ">=1.5,<2.0" -flake8-isort = ">=6.0,<7.0" -flake8-quotes = ">=3.0,<4.0" -flake8-rst-docstrings = ">=0.3,<0.4" -flake8-string-format = ">=0.3,<0.4" -pep8-naming = ">=0.13,<0.14" +flake8 = ">=7.1,<8.0" pygments = ">=2.4,<3.0" -setuptools = "*" -typing_extensions = ">=4.0,<5.0" - -[[package]] -name = "win32-setctime" -version = "1.2.0" -description = "A small Python utility to set file creation time on Windows" -optional = false -python-versions = ">=3.5" -files = [ - {file = "win32_setctime-1.2.0-py3-none-any.whl", hash = "sha256:95d644c4e708aba81dc3704a116d8cbc974d70b3bdb8be1d150e36be6e9d1390"}, - {file = "win32_setctime-1.2.0.tar.gz", hash = "sha256:ae1fdf948f5640aae05c511ade119313fb6a30d7eabe25fef9764dca5873c4c0"}, -] - -[package.extras] -dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"] [extras] check-laws = ["hypothesis", "pytest"] @@ -2634,4 +1779,4 @@ compatible-mypy = ["mypy"] [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "348ccae8ac4a6a09d3f4cce716fff5952ed0cd387c8fc17dd6f89ce6c4495121" +content-hash = "22381bbeead975745a658ce171ac3daae3209e9a3607a481637bcdaf5562f8ab" diff --git a/pyproject.toml b/pyproject.toml index 1feeb65e5..8ea08ff47 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,8 @@ +[build-system] +build-backend = "poetry.core.masonry.api" + +requires = [ "poetry-core>=1.9" ] + [tool.poetry] name = "returns" version = "0.24.0" @@ -5,7 +10,7 @@ description = "Make your functions return something meaningful, typed, and safe! license = "BSD-3-Clause" authors = [ - "sobolevn " + "sobolevn ", ] readme = "README.md" @@ -22,7 +27,7 @@ keywords = [ "composition", "type-safety", "mypy", - "railway-oriented-programming" + "railway-oriented-programming", ] classifiers = [ @@ -32,7 +37,7 @@ classifiers = [ "Framework :: Hypothesis", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Utilities", - "Typing :: Typed" + "Typing :: Typed", ] [tool.poetry.urls] @@ -44,41 +49,38 @@ returns = "returns.contrib.pytest.plugin" [tool.poetry.plugins.hypothesis] _ = "returns.contrib.hypothesis._entrypoint:_setup_hook" - [tool.poetry.dependencies] python = "^3.10" typing-extensions = ">=4.0,<5.0" pytest = { version = "^8.0", optional = true } hypothesis = { version = "^6.122", optional = true } -mypy = {version = ">=1.12,<1.15", optional = true} +mypy = { version = ">=1.12,<1.15", optional = true } [tool.poetry.group.dev.dependencies] anyio = "^4.3" -trio = ">=0.27,<0.29" +trio = "^0.28" attrs = "^24.2" -httpx = ">=0.27,<0.29" +httpx = "^0.28" -wemake-python-styleguide = "^0.19" -flake8-pytest-style = "^2.0" -flake8-pyi = "^24.1" -nitpick = "^0.35" +wemake-python-styleguide = "^1.0" codespell = "^2.2" slotscheck = "^0.19" +ruff = "^0.8" pytest-cov = "^6.0" pytest-randomly = "^3.12" pytest-mypy-plugins = "^3.1" -pytest-subtests = ">=0.13,<0.15" +pytest-subtests = "^0.14" pytest-shard = "^0.1" - +covdefaults = "^2.3" [tool.poetry.group.docs] optional = true [tool.poetry.group.docs.dependencies] -sphinx = ">=7.3,<9.0" +sphinx = "^8.1" sphinx-autodoc-typehints = "^2.3" sphinxcontrib-mermaid = "^1.0" furo = "^2024.5" @@ -86,18 +88,114 @@ myst-parser = "^4.0" tomli = "^2.0" [tool.poetry.extras] -compatible-mypy = ["mypy"] -check-laws = ["pytest", "hypothesis"] - - -[build-system] -requires = ["poetry-core>=1.9.0"] -build-backend = "poetry.core.masonry.api" - - -[tool.nitpick] -style = "https://raw.githubusercontent.com/wemake-services/wemake-python-styleguide/0.19.2/styles/nitpick-style-wemake.toml" +compatible-mypy = [ "mypy" ] +check-laws = [ "pytest", "hypothesis" ] + +[tool.ruff] +# Ruff config: https://docs.astral.sh/ruff/settings +target-version = "py310" +line-length = 80 +extend-exclude = [ + # Intentionally bad code: + "tests/**/__snapshots__/**", + "tests/fixtures/**", +] +preview = true +fix = true +format.quote-style = "single" +format.docstring-code-format = false +lint.select = [ + "A", # flake8-builtins + "B", # flake8-bugbear + "C4", # flake8-comprehensions + "C90", # maccabe + "COM", # flake8-commas + "D", # pydocstyle + "DTZ", # flake8-datetimez + "E", # pycodestyle + "ERA", # flake8-eradicate + "EXE", # flake8-executable + "F", # pyflakes + "FBT", # flake8-boolean-trap + "FLY", # pyflint + "FURB", # refurb + "G", # flake8-logging-format + "I", # isort + "ICN", # flake8-import-conventions + "ISC", # flake8-implicit-str-concat + "LOG", # flake8-logging + "N", # pep8-naming + "PERF", # perflint + "PIE", # flake8-pie + "PL", # pylint + "PT", # flake8-pytest-style + "PTH", # flake8-use-pathlib + "PYI", # flake8-pyi + "Q", # flake8-quotes + "RET", # flake8-return + "RSE", # flake8-raise + "RUF", # ruff + "S", # flake8-bandit + "SIM", # flake8-simpify + "SLF", # flake8-self + "SLOT", # flake8-slots + "T100", # flake8-debugger + "TRY", # tryceratops + "UP", # pyupgrade + "W", # pycodestyle + "YTT", # flake8-2020 +] +lint.ignore = [ + "A005", # allow to shadow stdlib and builtin module names + "COM812", # trailing comma, conflicts with `ruff format` + # Different doc rules that we don't really care about: + "D100", + "D104", + "D106", + "D203", + "D212", + "D401", + "D404", + "D405", + "ISC001", # implicit string concat conflicts with `ruff format` + "ISC003", # prefer explicit string concat over implicit concat + "PLR09", # we have our own complexity rules + "PLR2004", # do not report magic numbers + "PLR6301", # do not require classmethod / staticmethod when self not used + "TRY003", # long exception messages from `tryceratops` +] +lint.per-file-ignores."*.pyi" = [ "D103" ] +lint.per-file-ignores."returns/context/__init__.py" = [ "F401", "PLC0414" ] +lint.per-file-ignores."returns/contrib/mypy/*.py" = [ "S101" ] +lint.per-file-ignores."returns/contrib/mypy/_typeops/visitor.py" = [ "S101" ] +lint.per-file-ignores."returns/contrib/pytest/__init__.py" = [ "F401", "PLC0414" ] +lint.per-file-ignores."returns/interfaces/*.py" = [ "S101" ] +lint.per-file-ignores."returns/methods/__init__.py" = [ "F401", "PLC0414" ] +lint.per-file-ignores."returns/pipeline.py" = [ "F401", "PLC0414" ] +lint.per-file-ignores."returns/pointfree/__init__.py" = [ "F401", "PLC0414" ] +lint.per-file-ignores."returns/primitives/asserts.py" = [ "S101" ] +lint.per-file-ignores."tests/*.py" = [ + "RUF029", # allow async functions to not use `await` + "S101", # asserts + "S105", # hardcoded passwords + "S404", # subprocess calls are for tests + "S603", # do not require `shell=True` + "S607", # partial executable paths +] +lint.per-file-ignores."tests/test_examples/*" = [ "D102" ] +lint.per-file-ignores."tests/test_examples/test_maybe/test_maybe_pattern_matching.py" = [ + "D101", + "D103", + "F811", +] +lint.per-file-ignores."tests/test_examples/test_result/test_result_pattern_matching.py" = [ "D103" ] +lint.per-file-ignores."tests/test_pattern_matching.py" = [ "S101" ] +lint.external = [ "WPS" ] +lint.flake8-quotes.inline-quotes = "single" +lint.mccabe.max-complexity = 6 +lint.pep8-naming.staticmethod-decorators = [ "law_definition", "staticmethod" ] +lint.pydocstyle.convention = "google" [tool.slotscheck] strict-imports = true diff --git a/returns/_internal/futures/_future.py b/returns/_internal/futures/_future.py index c0c8f6850..99a6660c0 100644 --- a/returns/_internal/futures/_future.py +++ b/returns/_internal/futures/_future.py @@ -5,39 +5,39 @@ from returns.primitives.hkt import Kind1, dekind if TYPE_CHECKING: - from returns.future import Future # noqa: F401 + from returns.future import Future -_ValueType = TypeVar('_ValueType', covariant=True) +_ValueType_co = TypeVar('_ValueType_co', covariant=True) _NewValueType = TypeVar('_NewValueType') async def async_map( - function: Callable[[_ValueType], _NewValueType], - inner_value: Awaitable[_ValueType], + function: Callable[[_ValueType_co], _NewValueType], + inner_value: Awaitable[_ValueType_co], ) -> _NewValueType: """Async maps a function over a value.""" return function(await inner_value) async def async_apply( - container: 'Future[Callable[[_ValueType], _NewValueType]]', - inner_value: Awaitable[_ValueType], + container: 'Future[Callable[[_ValueType_co], _NewValueType]]', + inner_value: Awaitable[_ValueType_co], ) -> _NewValueType: """Async applies a container with function over a value.""" - return (await container)._inner_value(await inner_value) + return (await container)._inner_value(await inner_value) # noqa: SLF001 async def async_bind( - function: Callable[[_ValueType], Kind1['Future', _NewValueType]], - inner_value: Awaitable[_ValueType], + function: Callable[[_ValueType_co], Kind1['Future', _NewValueType]], + inner_value: Awaitable[_ValueType_co], ) -> _NewValueType: """Async binds a container over a value.""" - return (await dekind(function(await inner_value)))._inner_value + return (await dekind(function(await inner_value)))._inner_value # noqa: SLF001 async def async_bind_awaitable( - function: Callable[[_ValueType], Awaitable[_NewValueType]], - inner_value: Awaitable[_ValueType], + function: Callable[[_ValueType_co], Awaitable[_NewValueType]], + inner_value: Awaitable[_ValueType_co], ) -> _NewValueType: """Async binds a coroutine over a value.""" return await function(await inner_value) @@ -45,19 +45,19 @@ async def async_bind_awaitable( async def async_bind_async( function: Callable[ - [_ValueType], + [_ValueType_co], Awaitable[Kind1['Future', _NewValueType]], ], - inner_value: Awaitable[_ValueType], + inner_value: Awaitable[_ValueType_co], ) -> _NewValueType: """Async binds a coroutine with container over a value.""" - inner_io = dekind(await function(await inner_value))._inner_value + inner_io = dekind(await function(await inner_value))._inner_value # noqa: SLF001 return await inner_io async def async_bind_io( - function: Callable[[_ValueType], IO[_NewValueType]], - inner_value: Awaitable[_ValueType], + function: Callable[[_ValueType_co], IO[_NewValueType]], + inner_value: Awaitable[_ValueType_co], ) -> _NewValueType: """Async binds a container over a value.""" - return function(await inner_value)._inner_value + return function(await inner_value)._inner_value # noqa: SLF001 diff --git a/returns/_internal/futures/_future_result.py b/returns/_internal/futures/_future_result.py index d6ca49d07..0778a3311 100644 --- a/returns/_internal/futures/_future_result.py +++ b/returns/_internal/futures/_future_result.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from collections.abc import Awaitable, Callable from typing import TYPE_CHECKING, Any, TypeVar @@ -6,57 +8,58 @@ from returns.result import Failure, Result, Success if TYPE_CHECKING: - from returns.future import Future, FutureResult # noqa: F401 + from returns.future import Future, FutureResult -_ValueType = TypeVar('_ValueType', covariant=True) +_ValueType_co = TypeVar('_ValueType_co', covariant=True) _NewValueType = TypeVar('_NewValueType') -_ErrorType = TypeVar('_ErrorType', covariant=True) +_ErrorType_co = TypeVar('_ErrorType_co', covariant=True) _NewErrorType = TypeVar('_NewErrorType') async def async_swap( - inner_value: Awaitable[Result[_ValueType, _ErrorType]], -) -> Result[_ErrorType, _ValueType]: + inner_value: Awaitable[Result[_ValueType_co, _ErrorType_co]], +) -> Result[_ErrorType_co, _ValueType_co]: """Swaps value and error types in ``Result``.""" return (await inner_value).swap() async def async_map( - function: Callable[[_ValueType], _NewValueType], - inner_value: Awaitable[Result[_ValueType, _ErrorType]], -) -> Result[_NewValueType, _ErrorType]: + function: Callable[[_ValueType_co], _NewValueType], + inner_value: Awaitable[Result[_ValueType_co, _ErrorType_co]], +) -> Result[_NewValueType, _ErrorType_co]: """Async maps a function over a value.""" return (await inner_value).map(function) async def async_apply( - container: - 'FutureResult[Callable[[_ValueType], _NewValueType], _ErrorType]', - inner_value: Awaitable[Result[_ValueType, _ErrorType]], -) -> Result[_NewValueType, _ErrorType]: + container: FutureResult[ + Callable[[_ValueType_co], _NewValueType], _ErrorType_co + ], + inner_value: Awaitable[Result[_ValueType_co, _ErrorType_co]], +) -> Result[_NewValueType, _ErrorType_co]: """Async maps a function over a value.""" - return (await inner_value).apply((await container)._inner_value) + return (await inner_value).apply((await container)._inner_value) # noqa: SLF001 async def async_bind( function: Callable[ - [_ValueType], - Kind2['FutureResult', _NewValueType, _ErrorType], + [_ValueType_co], + Kind2[FutureResult, _NewValueType, _ErrorType_co], ], - inner_value: Awaitable[Result[_ValueType, _ErrorType]], -) -> Result[_NewValueType, _ErrorType]: + inner_value: Awaitable[Result[_ValueType_co, _ErrorType_co]], +) -> Result[_NewValueType, _ErrorType_co]: """Async binds a container over a value.""" container = await inner_value if isinstance(container, Success): - return (await dekind(function(container.unwrap())))._inner_value + return (await dekind(function(container.unwrap())))._inner_value # noqa: SLF001 return container # type: ignore[return-value] async def async_bind_awaitable( - function: Callable[[_ValueType], Awaitable[_NewValueType]], - inner_value: Awaitable[Result[_ValueType, _ErrorType]], -) -> Result[_NewValueType, _ErrorType]: + function: Callable[[_ValueType_co], Awaitable[_NewValueType]], + inner_value: Awaitable[Result[_ValueType_co, _ErrorType_co]], +) -> Result[_NewValueType, _ErrorType_co]: """Async binds a coroutine over a value.""" container = await inner_value if isinstance(container, Success): @@ -66,52 +69,52 @@ async def async_bind_awaitable( async def async_bind_async( function: Callable[ - [_ValueType], - Awaitable[Kind2['FutureResult', _NewValueType, _ErrorType]], + [_ValueType_co], + Awaitable[Kind2[FutureResult, _NewValueType, _ErrorType_co]], ], - inner_value: Awaitable[Result[_ValueType, _ErrorType]], -) -> Result[_NewValueType, _ErrorType]: + inner_value: Awaitable[Result[_ValueType_co, _ErrorType_co]], +) -> Result[_NewValueType, _ErrorType_co]: """Async binds a coroutine with container over a value.""" container = await inner_value if isinstance(container, Success): - return await dekind(await function(container.unwrap()))._inner_value + return await dekind(await function(container.unwrap()))._inner_value # noqa: SLF001 return container # type: ignore[return-value] async def async_bind_result( - function: Callable[[_ValueType], Result[_NewValueType, _ErrorType]], - inner_value: Awaitable[Result[_ValueType, _ErrorType]], -) -> Result[_NewValueType, _ErrorType]: + function: Callable[[_ValueType_co], Result[_NewValueType, _ErrorType_co]], + inner_value: Awaitable[Result[_ValueType_co, _ErrorType_co]], +) -> Result[_NewValueType, _ErrorType_co]: """Async binds a container returning ``Result`` over a value.""" return (await inner_value).bind(function) async def async_bind_ioresult( - function: Callable[[_ValueType], IOResult[_NewValueType, _ErrorType]], - inner_value: Awaitable[Result[_ValueType, _ErrorType]], -) -> Result[_NewValueType, _ErrorType]: + function: Callable[[_ValueType_co], IOResult[_NewValueType, _ErrorType_co]], + inner_value: Awaitable[Result[_ValueType_co, _ErrorType_co]], +) -> Result[_NewValueType, _ErrorType_co]: """Async binds a container returning ``IOResult`` over a value.""" container = await inner_value if isinstance(container, Success): - return function(container.unwrap())._inner_value + return function(container.unwrap())._inner_value # noqa: SLF001 return container # type: ignore[return-value] async def async_bind_io( - function: Callable[[_ValueType], IO[_NewValueType]], - inner_value: Awaitable[Result[_ValueType, _ErrorType]], -) -> Result[_NewValueType, _ErrorType]: + function: Callable[[_ValueType_co], IO[_NewValueType]], + inner_value: Awaitable[Result[_ValueType_co, _ErrorType_co]], +) -> Result[_NewValueType, _ErrorType_co]: """Async binds a container returning ``IO`` over a value.""" container = await inner_value if isinstance(container, Success): - return Success(function(container.unwrap())._inner_value) + return Success(function(container.unwrap())._inner_value) # noqa: SLF001 return container # type: ignore[return-value] async def async_bind_future( - function: Callable[[_ValueType], 'Future[_NewValueType]'], - inner_value: Awaitable[Result[_ValueType, _ErrorType]], -) -> Result[_NewValueType, _ErrorType]: + function: Callable[[_ValueType_co], Future[_NewValueType]], + inner_value: Awaitable[Result[_ValueType_co, _ErrorType_co]], +) -> Result[_NewValueType, _ErrorType_co]: """Async binds a container returning ``IO`` over a value.""" container = await inner_value if isinstance(container, Success): @@ -120,9 +123,9 @@ async def async_bind_future( async def async_bind_async_future( - function: Callable[[_ValueType], Awaitable['Future[_NewValueType]']], - inner_value: Awaitable[Result[_ValueType, _ErrorType]], -) -> Result[_NewValueType, _ErrorType]: + function: Callable[[_ValueType_co], Awaitable[Future[_NewValueType]]], + inner_value: Awaitable[Result[_ValueType_co, _ErrorType_co]], +) -> Result[_NewValueType, _ErrorType_co]: """Async binds a container returning ``IO`` over a value.""" container = await inner_value if isinstance(container, Success): @@ -131,9 +134,9 @@ async def async_bind_async_future( async def async_alt( - function: Callable[[_ErrorType], _NewErrorType], - inner_value: Awaitable[Result[_ValueType, _ErrorType]], -) -> Result[_ValueType, _NewErrorType]: + function: Callable[[_ErrorType_co], _NewErrorType], + inner_value: Awaitable[Result[_ValueType_co, _ErrorType_co]], +) -> Result[_ValueType_co, _NewErrorType]: """Async alts a function over a value.""" container = await inner_value if isinstance(container, Success): @@ -143,38 +146,38 @@ async def async_alt( async def async_lash( function: Callable[ - [_ErrorType], - Kind2['FutureResult', _ValueType, _NewErrorType], + [_ErrorType_co], + Kind2[FutureResult, _ValueType_co, _NewErrorType], ], - inner_value: Awaitable[Result[_ValueType, _ErrorType]], -) -> Result[_ValueType, _NewErrorType]: + inner_value: Awaitable[Result[_ValueType_co, _ErrorType_co]], +) -> Result[_ValueType_co, _NewErrorType]: """Async lashes a function returning a container over a value.""" container = await inner_value if isinstance(container, Success): return container - return (await dekind(function(container.failure())))._inner_value + return (await dekind(function(container.failure())))._inner_value # noqa: SLF001 async def async_from_success( - container: 'Future[_NewValueType]', + container: Future[_NewValueType], ) -> Result[_NewValueType, Any]: """Async success unit factory.""" - return Success((await container)._inner_value) + return Success((await container)._inner_value) # noqa: SLF001 async def async_from_failure( - container: 'Future[_NewErrorType]', + container: Future[_NewErrorType], ) -> Result[Any, _NewErrorType]: """Async failure unit factory.""" - return Failure((await container)._inner_value) + return Failure((await container)._inner_value) # noqa: SLF001 async def async_compose_result( function: Callable[ - [Result[_ValueType, _ErrorType]], - Kind2['FutureResult', _NewValueType, _ErrorType], + [Result[_ValueType_co, _ErrorType_co]], + Kind2[FutureResult, _NewValueType, _ErrorType_co], ], - inner_value: Awaitable[Result[_ValueType, _ErrorType]], -) -> Result[_NewValueType, _ErrorType]: + inner_value: Awaitable[Result[_ValueType_co, _ErrorType_co]], +) -> Result[_NewValueType, _ErrorType_co]: """Async composes ``Result`` based function.""" - return (await dekind(function(await inner_value)))._inner_value + return (await dekind(function(await inner_value)))._inner_value # noqa: SLF001 diff --git a/returns/_internal/futures/_reader_future_result.py b/returns/_internal/futures/_reader_future_result.py index 710dddf6c..57ff789a8 100644 --- a/returns/_internal/futures/_reader_future_result.py +++ b/returns/_internal/futures/_reader_future_result.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from collections.abc import Awaitable, Callable from typing import TYPE_CHECKING, TypeVar @@ -5,33 +7,35 @@ from returns.result import Result, Success if TYPE_CHECKING: - from returns.context import RequiresContextFutureResult # noqa: F401 + from returns.context import RequiresContextFutureResult -_ValueType = TypeVar('_ValueType', covariant=True) +_ValueType_co = TypeVar('_ValueType_co', covariant=True) _NewValueType = TypeVar('_NewValueType') -_ErrorType = TypeVar('_ErrorType', covariant=True) +_ErrorType_co = TypeVar('_ErrorType_co', covariant=True) _EnvType = TypeVar('_EnvType') async def async_bind_async( function: Callable[ - [_ValueType], + [_ValueType_co], Awaitable[ Kind3[ - 'RequiresContextFutureResult', + RequiresContextFutureResult, _NewValueType, - _ErrorType, + _ErrorType_co, _EnvType, ], ], ], - container: 'RequiresContextFutureResult[_ValueType, _ErrorType, _EnvType]', + container: RequiresContextFutureResult[ + _ValueType_co, _ErrorType_co, _EnvType + ], deps: _EnvType, -) -> Result[_NewValueType, _ErrorType]: +) -> Result[_NewValueType, _ErrorType_co]: """Async binds a coroutine with container over a value.""" - inner_value = await container(deps)._inner_value + inner_value = await container(deps)._inner_value # noqa: SLF001 if isinstance(inner_value, Success): - return await dekind( + return await dekind( # noqa: SLF001 await function(inner_value.unwrap()), )(deps)._inner_value return inner_value # type: ignore[return-value] @@ -39,17 +43,19 @@ async def async_bind_async( async def async_compose_result( function: Callable[ - [Result[_ValueType, _ErrorType]], + [Result[_ValueType_co, _ErrorType_co]], Kind3[ - 'RequiresContextFutureResult', + RequiresContextFutureResult, _NewValueType, - _ErrorType, + _ErrorType_co, _EnvType, ], ], - container: 'RequiresContextFutureResult[_ValueType, _ErrorType, _EnvType]', + container: RequiresContextFutureResult[ + _ValueType_co, _ErrorType_co, _EnvType + ], deps: _EnvType, -) -> Result[_NewValueType, _ErrorType]: +) -> Result[_NewValueType, _ErrorType_co]: """Async composes ``Result`` based function.""" - new_container = dekind(function((await container(deps))._inner_value)) - return (await new_container(deps))._inner_value + new_container = dekind(function((await container(deps))._inner_value)) # noqa: SLF001 + return (await new_container(deps))._inner_value # noqa: SLF001 diff --git a/returns/_internal/pipeline/managed.py b/returns/_internal/pipeline/managed.py index d5c44c909..40bbdc928 100644 --- a/returns/_internal/pipeline/managed.py +++ b/returns/_internal/pipeline/managed.py @@ -22,10 +22,12 @@ def managed( [_FirstType, Result[_UpdatedType, _SecondType]], KindN[_IOResultLikeType, None, _SecondType, _ThirdType], ], -) -> Kinded[Callable[ - [KindN[_IOResultLikeType, _FirstType, _SecondType, _ThirdType]], - KindN[_IOResultLikeType, _UpdatedType, _SecondType, _ThirdType], -]]: +) -> Kinded[ + Callable[ + [KindN[_IOResultLikeType, _FirstType, _SecondType, _ThirdType]], + KindN[_IOResultLikeType, _UpdatedType, _SecondType, _ThirdType], + ] +]: """ Allows to run managed computation. @@ -90,11 +92,13 @@ def managed( But, we do not recommend to use this function with ``lambda`` functions. """ + @kinded def factory( acquire: KindN[_IOResultLikeType, _FirstType, _SecondType, _ThirdType], ) -> KindN[_IOResultLikeType, _UpdatedType, _SecondType, _ThirdType]: return acquire.bind(_use(acquire, use, release)) + return factory diff --git a/returns/_internal/pipeline/pipe.pyi b/returns/_internal/pipeline/pipe.pyi index 43c313c0b..7efe14abd 100644 --- a/returns/_internal/pipeline/pipe.pyi +++ b/returns/_internal/pipeline/pipe.pyi @@ -24,38 +24,32 @@ _PipelineStepType18 = TypeVar('_PipelineStepType18') _PipelineStepType19 = TypeVar('_PipelineStepType19') _PipelineStepType20 = TypeVar('_PipelineStepType20') - -class _Pipe(Generic[ - _InstanceType, - _ReturnType, - _PipelineStepType1, - _PipelineStepType2, - _PipelineStepType3, - _PipelineStepType4, - _PipelineStepType5, - _PipelineStepType6, - _PipelineStepType7, - _PipelineStepType8, - _PipelineStepType9, - _PipelineStepType10, - _PipelineStepType11, - _PipelineStepType12, - _PipelineStepType13, - _PipelineStepType14, - _PipelineStepType15, - _PipelineStepType16, - _PipelineStepType17, - _PipelineStepType18, - _PipelineStepType19, - _PipelineStepType20, -]): - """ - Internal type to make ``mypy`` plugin work correctly. - - We need this to be able to check ``__call__`` signature. - See docs on ``pipe`` feature in ``mypy`` plugin. - """ - +class _Pipe( + Generic[ + _InstanceType, + _ReturnType, + _PipelineStepType1, + _PipelineStepType2, + _PipelineStepType3, + _PipelineStepType4, + _PipelineStepType5, + _PipelineStepType6, + _PipelineStepType7, + _PipelineStepType8, + _PipelineStepType9, + _PipelineStepType10, + _PipelineStepType11, + _PipelineStepType12, + _PipelineStepType13, + _PipelineStepType14, + _PipelineStepType15, + _PipelineStepType16, + _PipelineStepType17, + _PipelineStepType18, + _PipelineStepType19, + _PipelineStepType20, + ] +): def __init__( # noqa: WPS451 self, functions: tuple[ @@ -81,12 +75,8 @@ class _Pipe(Generic[ _PipelineStepType20, ], /, - ) -> None: - ... - - def __call__(self, instance: _InstanceType) -> _ReturnType: - ... - + ) -> None: ... + def __call__(self, instance: _InstanceType) -> _ReturnType: ... def pipe( # noqa: WPS451 function1: _PipelineStepType1, @@ -133,5 +123,4 @@ def pipe( # noqa: WPS451 _PipelineStepType18, _PipelineStepType19, _PipelineStepType20, -]: - ... +]: ... diff --git a/returns/context/requires_context.py b/returns/context/requires_context.py index 46e6434b4..369ae7e99 100644 --- a/returns/context/requires_context.py +++ b/returns/context/requires_context.py @@ -23,9 +23,9 @@ from returns.context.requires_context_result import RequiresContextResult # Context: -_EnvType = TypeVar('_EnvType', contravariant=True) +_EnvType_contra = TypeVar('_EnvType_contra', contravariant=True) _NewEnvType = TypeVar('_NewEnvType') -_ReturnType = TypeVar('_ReturnType', covariant=True) +_ReturnType_co = TypeVar('_ReturnType_co', covariant=True) _NewReturnType = TypeVar('_NewReturnType') _ValueType = TypeVar('_ValueType') @@ -43,8 +43,8 @@ @final class RequiresContext( # type: ignore[type-var] BaseContainer, - SupportsKind2['RequiresContext', _ReturnType, _EnvType], - reader.ReaderBased2[_ReturnType, _EnvType], + SupportsKind2['RequiresContext', _ReturnType_co, _EnvType_contra], + reader.ReaderBased2[_ReturnType_co, _EnvType_contra], ): """ The ``RequiresContext`` container. @@ -79,14 +79,14 @@ class RequiresContext( # type: ignore[type-var] __slots__ = () #: This field has an extra 'RequiresContext' just because `mypy` needs it. - _inner_value: Callable[[_EnvType], _ReturnType] + _inner_value: Callable[[_EnvType_contra], _ReturnType_co] #: A convenient placeholder to call methods created by `.from_value()`: no_args: ClassVar[NoDeps] = object() def __init__( self, - inner_value: Callable[[_EnvType], _ReturnType], + inner_value: Callable[[_EnvType_contra], _ReturnType_co], ) -> None: """ Public constructor for this type. Also required for typing. @@ -102,7 +102,7 @@ def __init__( """ super().__init__(inner_value) - def __call__(self, deps: _EnvType) -> _ReturnType: + def __call__(self, deps: _EnvType_contra) -> _ReturnType_co: """ Evaluates the wrapped function. @@ -127,8 +127,9 @@ def __call__(self, deps: _EnvType) -> _ReturnType: return self._inner_value(deps) def map( - self, function: Callable[[_ReturnType], _NewReturnType], - ) -> RequiresContext[_NewReturnType, _EnvType]: + self, + function: Callable[[_ReturnType_co], _NewReturnType], + ) -> RequiresContext[_NewReturnType, _EnvType_contra]: """ Allows to compose functions inside the wrapped container. @@ -153,10 +154,10 @@ def apply( self, container: Kind2[ RequiresContext, - Callable[[_ReturnType], _NewReturnType], - _EnvType, + Callable[[_ReturnType_co], _NewReturnType], + _EnvType_contra, ], - ) -> RequiresContext[_NewReturnType, _EnvType]: + ) -> RequiresContext[_NewReturnType, _EnvType_contra]: """ Calls a wrapped function in a container on this container. @@ -175,10 +176,10 @@ def apply( def bind( self, function: Callable[ - [_ReturnType], - Kind2[RequiresContext, _NewReturnType, _EnvType], + [_ReturnType_co], + Kind2[RequiresContext, _NewReturnType, _EnvType_contra], ], - ) -> RequiresContext[_NewReturnType, _EnvType]: + ) -> RequiresContext[_NewReturnType, _EnvType_contra]: """ Composes a container with a function returning another container. @@ -212,8 +213,8 @@ def bind( def modify_env( self, - function: Callable[[_NewEnvType], _EnvType], - ) -> RequiresContext[_ReturnType, _NewEnvType]: + function: Callable[[_NewEnvType], _EnvType_contra], + ) -> RequiresContext[_ReturnType_co, _NewEnvType]: """ Allows to modify the environment type. @@ -230,7 +231,7 @@ def modify_env( return RequiresContext(lambda deps: self(function(deps))) @classmethod - def ask(cls) -> RequiresContext[_EnvType, _EnvType]: + def ask(cls) -> RequiresContext[_EnvType_contra, _EnvType_contra]: """ Get current context to use the dependencies. @@ -308,12 +309,13 @@ def ask(cls) -> RequiresContext[_EnvType, _EnvType]: See also: - https://dev.to/gcanti/getting-started-with-fp-ts-reader-1ie5 - """ # noqa: F811 + """ return RequiresContext(identity) @classmethod def from_value( - cls, inner_value: _FirstType, + cls, + inner_value: _FirstType, ) -> RequiresContext[_FirstType, NoDeps]: """ Used to return some specific value from the container. @@ -335,7 +337,8 @@ def from_value( @classmethod def from_context( - cls, inner_value: RequiresContext[_NewReturnType, _NewEnvType], + cls, + inner_value: RequiresContext[_NewReturnType, _NewEnvType], ) -> RequiresContext[_NewReturnType, _NewEnvType]: """ Used to create new containers from existing ones. @@ -354,8 +357,10 @@ def from_context( @classmethod def from_requires_context_result( cls, - inner_value: RequiresContextResult[_ValueType, _ErrorType, _EnvType], - ) -> RequiresContext[Result[_ValueType, _ErrorType], _EnvType]: + inner_value: RequiresContextResult[ + _ValueType, _ErrorType, _EnvType_contra + ], + ) -> RequiresContext[Result[_ValueType, _ErrorType], _EnvType_contra]: """ Typecasts ``RequiresContextResult`` to ``RequiresContext`` instance. @@ -379,9 +384,10 @@ def from_requires_context_result( @classmethod def from_requires_context_ioresult( cls, - inner_value: - RequiresContextIOResult[_ValueType, _ErrorType, _EnvType], - ) -> RequiresContext[IOResult[_ValueType, _ErrorType], _EnvType]: + inner_value: RequiresContextIOResult[ + _ValueType, _ErrorType, _EnvType_contra + ], + ) -> RequiresContext[IOResult[_ValueType, _ErrorType], _EnvType_contra]: """ Typecasts ``RequiresContextIOResult`` to ``RequiresContext`` instance. @@ -406,9 +412,11 @@ def from_requires_context_ioresult( def from_requires_context_future_result( cls, inner_value: RequiresContextFutureResult[ - _ValueType, _ErrorType, _EnvType, + _ValueType, + _ErrorType, + _EnvType_contra, ], - ) -> RequiresContext[FutureResult[_ValueType, _ErrorType], _EnvType]: + ) -> RequiresContext[FutureResult[_ValueType, _ErrorType], _EnvType_contra]: """ Typecasts ``RequiresContextIOResult`` to ``RequiresContext`` instance. diff --git a/returns/context/requires_context_future_result.py b/returns/context/requires_context_future_result.py index bb54b5559..b93069f43 100644 --- a/returns/context/requires_context_future_result.py +++ b/returns/context/requires_context_future_result.py @@ -21,13 +21,13 @@ from returns.context.requires_context_result import RequiresContextResult # Context: -_EnvType = TypeVar('_EnvType', contravariant=True) +_EnvType_contra = TypeVar('_EnvType_contra', contravariant=True) _NewEnvType = TypeVar('_NewEnvType') # Result: -_ValueType = TypeVar('_ValueType', covariant=True) +_ValueType_co = TypeVar('_ValueType_co', covariant=True) _NewValueType = TypeVar('_NewValueType') -_ErrorType = TypeVar('_ErrorType', covariant=True) +_ErrorType_co = TypeVar('_ErrorType_co', covariant=True) _NewErrorType = TypeVar('_NewErrorType') # Helpers: @@ -38,12 +38,19 @@ class RequiresContextFutureResult( # type: ignore[type-var] BaseContainer, SupportsKind3[ - 'RequiresContextFutureResult', _ValueType, _ErrorType, _EnvType, + 'RequiresContextFutureResult', + _ValueType_co, + _ErrorType_co, + _EnvType_contra, ], reader_future_result.ReaderFutureResultBasedN[ - _ValueType, _ErrorType, _EnvType, + _ValueType_co, + _ErrorType_co, + _EnvType_contra, + ], + future_result.FutureResultLike3[ + _ValueType_co, _ErrorType_co, _EnvType_contra ], - future_result.FutureResultLike3[_ValueType, _ErrorType, _EnvType], ): """ The ``RequiresContextFutureResult`` combinator. @@ -99,14 +106,18 @@ class RequiresContextFutureResult( # type: ignore[type-var] #: Inner value of `RequiresContext` #: is just a function that returns `FutureResult`. #: This field has an extra 'RequiresContext' just because `mypy` needs it. - _inner_value: Callable[[_EnvType], FutureResult[_ValueType, _ErrorType]] + _inner_value: Callable[ + [_EnvType_contra], FutureResult[_ValueType_co, _ErrorType_co] + ] #: A convenient placeholder to call methods created by `.from_value()`. no_args: ClassVar[NoDeps] = object() def __init__( self, - inner_value: Callable[[_EnvType], FutureResult[_ValueType, _ErrorType]], + inner_value: Callable[ + [_EnvType_contra], FutureResult[_ValueType_co, _ErrorType_co] + ], ) -> None: """ Public constructor for this type. Also required for typing. @@ -128,7 +139,9 @@ def __init__( """ super().__init__(inner_value) - def __call__(self, deps: _EnvType) -> FutureResult[_ValueType, _ErrorType]: + def __call__( + self, deps: _EnvType_contra + ) -> FutureResult[_ValueType_co, _ErrorType_co]: """ Evaluates the wrapped function. @@ -160,7 +173,9 @@ def __call__(self, deps: _EnvType) -> FutureResult[_ValueType, _ErrorType]: def swap( self, - ) -> RequiresContextFutureResult[_ErrorType, _ValueType, _EnvType]: + ) -> RequiresContextFutureResult[ + _ErrorType_co, _ValueType_co, _EnvType_contra + ]: """ Swaps value and error types. @@ -186,8 +201,10 @@ def swap( def map( self, - function: Callable[[_ValueType], _NewValueType], - ) -> RequiresContextFutureResult[_NewValueType, _ErrorType, _EnvType]: + function: Callable[[_ValueType_co], _NewValueType], + ) -> RequiresContextFutureResult[ + _NewValueType, _ErrorType_co, _EnvType_contra + ]: """ Composes successful container with a pure function. @@ -214,11 +231,13 @@ def apply( self, container: Kind3[ RequiresContextFutureResult, - Callable[[_ValueType], _NewValueType], - _ErrorType, - _EnvType, + Callable[[_ValueType_co], _NewValueType], + _ErrorType_co, + _EnvType_contra, ], - ) -> RequiresContextFutureResult[_NewValueType, _ErrorType, _EnvType]: + ) -> RequiresContextFutureResult[ + _NewValueType, _ErrorType_co, _EnvType_contra + ]: """ Calls a wrapped function in a container on this container. @@ -253,15 +272,17 @@ def apply( def bind( self, function: Callable[ - [_ValueType], + [_ValueType_co], Kind3[ RequiresContextFutureResult, _NewValueType, - _ErrorType, - _EnvType, + _ErrorType_co, + _EnvType_contra, ], ], - ) -> RequiresContextFutureResult[_NewValueType, _ErrorType, _EnvType]: + ) -> RequiresContextFutureResult[ + _NewValueType, _ErrorType_co, _EnvType_contra + ]: """ Composes this container with a function returning the same type. @@ -305,17 +326,19 @@ def bind( def bind_async( self, function: Callable[ - [_ValueType], + [_ValueType_co], Awaitable[ Kind3[ RequiresContextFutureResult, _NewValueType, - _ErrorType, - _EnvType, + _ErrorType_co, + _EnvType_contra, ], ], ], - ) -> RequiresContextFutureResult[_NewValueType, _ErrorType, _EnvType]: + ) -> RequiresContextFutureResult[ + _NewValueType, _ErrorType_co, _EnvType_contra + ]: """ Composes this container with a async function returning the same type. @@ -345,9 +368,13 @@ def bind_async( """ return RequiresContextFutureResult( - lambda deps: FutureResult(_reader_future_result.async_bind_async( - function, self, deps, - )), + lambda deps: FutureResult( + _reader_future_result.async_bind_async( + function, + self, + deps, + ) + ), ) #: Alias for `bind_async_context_future_result` method, @@ -356,8 +383,10 @@ def bind_async( def bind_awaitable( self, - function: Callable[[_ValueType], Awaitable[_NewValueType]], - ) -> RequiresContextFutureResult[_NewValueType, _ErrorType, _EnvType]: + function: Callable[[_ValueType_co], Awaitable[_NewValueType]], + ) -> RequiresContextFutureResult[ + _NewValueType, _ErrorType_co, _EnvType_contra + ]: """ Allows to compose a container and a regular ``async`` function. @@ -395,8 +424,12 @@ def bind_awaitable( def bind_result( self, - function: Callable[[_ValueType], Result[_NewValueType, _ErrorType]], - ) -> RequiresContextFutureResult[_NewValueType, _ErrorType, _EnvType]: + function: Callable[ + [_ValueType_co], Result[_NewValueType, _ErrorType_co] + ], + ) -> RequiresContextFutureResult[ + _NewValueType, _ErrorType_co, _EnvType_contra + ]: """ Binds ``Result`` returning function to the current container. @@ -432,10 +465,12 @@ def bind_result( def bind_context( self, function: Callable[ - [_ValueType], - RequiresContext[_NewValueType, _EnvType], + [_ValueType_co], + RequiresContext[_NewValueType, _EnvType_contra], ], - ) -> RequiresContextFutureResult[_NewValueType, _ErrorType, _EnvType]: + ) -> RequiresContextFutureResult[ + _NewValueType, _ErrorType_co, _EnvType_contra + ]: """ Binds ``RequiresContext`` returning function to current container. @@ -472,10 +507,14 @@ def bind_context( def bind_context_result( self, function: Callable[ - [_ValueType], - RequiresContextResult[_NewValueType, _ErrorType, _EnvType], + [_ValueType_co], + RequiresContextResult[ + _NewValueType, _ErrorType_co, _EnvType_contra + ], ], - ) -> RequiresContextFutureResult[_NewValueType, _ErrorType, _EnvType]: + ) -> RequiresContextFutureResult[ + _NewValueType, _ErrorType_co, _EnvType_contra + ]: """ Binds ``RequiresContextResult`` returning function to the current one. @@ -515,10 +554,14 @@ def bind_context_result( def bind_context_ioresult( self, function: Callable[ - [_ValueType], - RequiresContextIOResult[_NewValueType, _ErrorType, _EnvType], + [_ValueType_co], + RequiresContextIOResult[ + _NewValueType, _ErrorType_co, _EnvType_contra + ], ], - ) -> RequiresContextFutureResult[_NewValueType, _ErrorType, _EnvType]: + ) -> RequiresContextFutureResult[ + _NewValueType, _ErrorType_co, _EnvType_contra + ]: """ Binds ``RequiresContextIOResult`` returning function to the current one. @@ -556,8 +599,10 @@ def bind_context_ioresult( def bind_io( self, - function: Callable[[_ValueType], IO[_NewValueType]], - ) -> RequiresContextFutureResult[_NewValueType, _ErrorType, _EnvType]: + function: Callable[[_ValueType_co], IO[_NewValueType]], + ) -> RequiresContextFutureResult[ + _NewValueType, _ErrorType_co, _EnvType_contra + ]: """ Binds ``IO`` returning function to the current container. @@ -587,8 +632,12 @@ def bind_io( def bind_ioresult( self, - function: Callable[[_ValueType], IOResult[_NewValueType, _ErrorType]], - ) -> RequiresContextFutureResult[_NewValueType, _ErrorType, _EnvType]: + function: Callable[ + [_ValueType_co], IOResult[_NewValueType, _ErrorType_co] + ], + ) -> RequiresContextFutureResult[ + _NewValueType, _ErrorType_co, _EnvType_contra + ]: """ Binds ``IOResult`` returning function to the current container. @@ -622,8 +671,10 @@ def bind_ioresult( def bind_future( self, - function: Callable[[_ValueType], Future[_NewValueType]], - ) -> RequiresContextFutureResult[_NewValueType, _ErrorType, _EnvType]: + function: Callable[[_ValueType_co], Future[_NewValueType]], + ) -> RequiresContextFutureResult[ + _NewValueType, _ErrorType_co, _EnvType_contra + ]: """ Binds ``Future`` returning function to the current container. @@ -658,10 +709,12 @@ def bind_future( def bind_future_result( self, function: Callable[ - [_ValueType], - FutureResult[_NewValueType, _ErrorType], + [_ValueType_co], + FutureResult[_NewValueType, _ErrorType_co], ], - ) -> RequiresContextFutureResult[_NewValueType, _ErrorType, _EnvType]: + ) -> RequiresContextFutureResult[ + _NewValueType, _ErrorType_co, _EnvType_contra + ]: """ Binds ``FutureResult`` returning function to the current container. @@ -695,8 +748,10 @@ def bind_future_result( def bind_async_future( self, - function: Callable[[_ValueType], Awaitable[Future[_NewValueType]]], - ) -> RequiresContextFutureResult[_NewValueType, _ErrorType, _EnvType]: + function: Callable[[_ValueType_co], Awaitable[Future[_NewValueType]]], + ) -> RequiresContextFutureResult[ + _NewValueType, _ErrorType_co, _EnvType_contra + ]: """ Binds ``Future`` returning async function to the current container. @@ -731,10 +786,12 @@ def bind_async_future( def bind_async_future_result( self, function: Callable[ - [_ValueType], - Awaitable[FutureResult[_NewValueType, _ErrorType]], + [_ValueType_co], + Awaitable[FutureResult[_NewValueType, _ErrorType_co]], ], - ) -> RequiresContextFutureResult[_NewValueType, _ErrorType, _EnvType]: + ) -> RequiresContextFutureResult[ + _NewValueType, _ErrorType_co, _EnvType_contra + ]: """ Bind ``FutureResult`` returning async function to the current container. @@ -769,8 +826,11 @@ def bind_async_future_result( ) def alt( - self, function: Callable[[_ErrorType], _NewErrorType], - ) -> RequiresContextFutureResult[_ValueType, _NewErrorType, _EnvType]: + self, + function: Callable[[_ErrorType_co], _NewErrorType], + ) -> RequiresContextFutureResult[ + _ValueType_co, _NewErrorType, _EnvType_contra + ]: """ Composes failed container with a pure function. @@ -802,15 +862,17 @@ def alt( def lash( self, function: Callable[ - [_ErrorType], + [_ErrorType_co], Kind3[ RequiresContextFutureResult, - _ValueType, + _ValueType_co, _NewErrorType, - _EnvType, + _EnvType_contra, ], ], - ) -> RequiresContextFutureResult[_ValueType, _NewErrorType, _EnvType]: + ) -> RequiresContextFutureResult[ + _ValueType_co, _NewErrorType, _EnvType_contra + ]: """ Composes this container with a function returning the same type. @@ -852,15 +914,17 @@ def lash( def compose_result( self, function: Callable[ - [Result[_ValueType, _ErrorType]], + [Result[_ValueType_co, _ErrorType_co]], Kind3[ RequiresContextFutureResult, _NewValueType, - _ErrorType, - _EnvType, + _ErrorType_co, + _EnvType_contra, ], ], - ) -> RequiresContextFutureResult[_NewValueType, _ErrorType, _EnvType]: + ) -> RequiresContextFutureResult[ + _NewValueType, _ErrorType_co, _EnvType_contra + ]: """ Composes inner ``Result`` with ``ReaderFutureResult`` returning func. @@ -894,15 +958,17 @@ def compose_result( return RequiresContextFutureResult( lambda deps: FutureResult( _reader_future_result.async_compose_result( - function, self, deps, + function, + self, + deps, ), ), ) def modify_env( self, - function: Callable[[_NewEnvType], _EnvType], - ) -> RequiresContextFutureResult[_ValueType, _ErrorType, _NewEnvType]: + function: Callable[[_NewEnvType], _EnvType_contra], + ) -> RequiresContextFutureResult[_ValueType_co, _ErrorType_co, _NewEnvType]: """ Allows to modify the environment type. @@ -927,7 +993,9 @@ def modify_env( @classmethod def ask( cls, - ) -> RequiresContextFutureResult[_EnvType, _ErrorType, _EnvType]: + ) -> RequiresContextFutureResult[ + _EnvType_contra, _ErrorType_co, _EnvType_contra + ]: """ Is used to get the current dependencies inside the call stack. @@ -957,7 +1025,8 @@ def ask( @classmethod def from_result( - cls, inner_value: Result[_NewValueType, _NewErrorType], + cls, + inner_value: Result[_NewValueType, _NewErrorType], ) -> RequiresContextFutureResult[_NewValueType, _NewErrorType, NoDeps]: """ Creates new container with ``Result`` as a unit value. @@ -1034,7 +1103,8 @@ def from_failed_io( @classmethod def from_ioresult( - cls, inner_value: IOResult[_NewValueType, _NewErrorType], + cls, + inner_value: IOResult[_NewValueType, _NewErrorType], ) -> RequiresContextFutureResult[_NewValueType, _NewErrorType, NoDeps]: """ Creates new container with ``IOResult`` as a unit value. @@ -1115,8 +1185,9 @@ def from_failed_future( @classmethod def from_future_result_context( cls, - inner_value: - ReaderFutureResult[_NewValueType, _NewErrorType, _NewEnvType], + inner_value: ReaderFutureResult[ + _NewValueType, _NewErrorType, _NewEnvType + ], ) -> ReaderFutureResult[_NewValueType, _NewErrorType, _NewEnvType]: """ Creates new container with ``ReaderFutureResult`` as a unit value. @@ -1180,9 +1251,12 @@ def from_future_result( def from_typecast( cls, inner_value: RequiresContext[ - FutureResult[_NewValueType, _NewErrorType], _EnvType, + FutureResult[_NewValueType, _NewErrorType], + _EnvType_contra, ], - ) -> RequiresContextFutureResult[_NewValueType, _NewErrorType, _EnvType]: + ) -> RequiresContextFutureResult[ + _NewValueType, _NewErrorType, _EnvType_contra + ]: """ You might end up with ``RequiresContext[FutureResult]`` as a value. @@ -1217,7 +1291,8 @@ def from_typecast( @classmethod def from_context( - cls, inner_value: RequiresContext[_NewValueType, _NewEnvType], + cls, + inner_value: RequiresContext[_NewValueType, _NewEnvType], ) -> RequiresContextFutureResult[_NewValueType, Any, _NewEnvType]: """ Creates new container from ``RequiresContext`` as a success unit. @@ -1242,7 +1317,8 @@ def from_context( @classmethod def from_failed_context( - cls, inner_value: RequiresContext[_NewValueType, _NewEnvType], + cls, + inner_value: RequiresContext[_NewValueType, _NewEnvType], ) -> RequiresContextFutureResult[Any, _NewValueType, _NewEnvType]: """ Creates new container from ``RequiresContext`` as a failure unit. @@ -1269,7 +1345,9 @@ def from_failed_context( def from_result_context( cls, inner_value: RequiresContextResult[ - _NewValueType, _NewErrorType, _NewEnvType, + _NewValueType, + _NewErrorType, + _NewEnvType, ], ) -> ReaderFutureResult[_NewValueType, _NewErrorType, _NewEnvType]: """ @@ -1303,8 +1381,7 @@ def from_result_context( @classmethod def from_ioresult_context( cls, - inner_value: - ReaderIOResult[_NewValueType, _NewErrorType, _NewEnvType], + inner_value: ReaderIOResult[_NewValueType, _NewErrorType, _NewEnvType], ) -> ReaderFutureResult[_NewValueType, _NewErrorType, _NewEnvType]: """ Creates new container from ``RequiresContextIOResult`` as a unit value. @@ -1336,7 +1413,8 @@ def from_ioresult_context( @classmethod def from_value( - cls, inner_value: _FirstType, + cls, + inner_value: _FirstType, ) -> RequiresContextFutureResult[_FirstType, Any, NoDeps]: """ Creates new container with successful ``FutureResult`` as a unit value. @@ -1358,7 +1436,8 @@ def from_value( @classmethod def from_failure( - cls, inner_value: _FirstType, + cls, + inner_value: _FirstType, ) -> RequiresContextFutureResult[Any, _FirstType, NoDeps]: """ Creates new container with failed ``FutureResult`` as a unit value. @@ -1383,7 +1462,9 @@ def from_failure( #: Alias for a popular case when ``Result`` has ``Exception`` as error type. RequiresContextFutureResultE: TypeAlias = RequiresContextFutureResult[ - _ValueType, Exception, _EnvType, + _ValueType_co, + Exception, + _EnvType_contra, ] #: Sometimes `RequiresContextFutureResult` is too long to type. @@ -1391,5 +1472,7 @@ def from_failure( #: Alias to save you some typing. Uses ``Exception`` as error type. ReaderFutureResultE: TypeAlias = RequiresContextFutureResult[ - _ValueType, Exception, _EnvType, + _ValueType_co, + Exception, + _EnvType_contra, ] diff --git a/returns/context/requires_context_ioresult.py b/returns/context/requires_context_ioresult.py index b976c17e0..17a7b1925 100644 --- a/returns/context/requires_context_ioresult.py +++ b/returns/context/requires_context_ioresult.py @@ -15,24 +15,25 @@ from returns.context.requires_context_result import RequiresContextResult # Context: -_EnvType = TypeVar('_EnvType', contravariant=True) +_EnvType_contra = TypeVar('_EnvType_contra', contravariant=True) _NewEnvType = TypeVar('_NewEnvType') # Result: -_ValueType = TypeVar('_ValueType', covariant=True) +_ValueType_co = TypeVar('_ValueType_co', covariant=True) _NewValueType = TypeVar('_NewValueType') _ErrorType = TypeVar('_ErrorType') _NewErrorType = TypeVar('_NewErrorType') -# Helpers: -_FirstType = TypeVar('_FirstType') - @final class RequiresContextIOResult( # type: ignore[type-var] BaseContainer, - SupportsKind3['RequiresContextIOResult', _ValueType, _ErrorType, _EnvType], - reader_ioresult.ReaderIOResultBasedN[_ValueType, _ErrorType, _EnvType], + SupportsKind3[ + 'RequiresContextIOResult', _ValueType_co, _ErrorType, _EnvType_contra + ], + reader_ioresult.ReaderIOResultBasedN[ + _ValueType_co, _ErrorType, _EnvType_contra + ], ): """ The ``RequiresContextIOResult`` combinator. @@ -106,14 +107,18 @@ class RequiresContextIOResult( # type: ignore[type-var] #: Inner value of `RequiresContext` #: is just a function that returns `IOResult`. #: This field has an extra 'RequiresContext' just because `mypy` needs it. - _inner_value: Callable[[_EnvType], IOResult[_ValueType, _ErrorType]] + _inner_value: Callable[ + [_EnvType_contra], IOResult[_ValueType_co, _ErrorType] + ] #: A convenient placeholder to call methods created by `.from_value()`. no_args: ClassVar[NoDeps] = object() def __init__( self, - inner_value: Callable[[_EnvType], IOResult[_ValueType, _ErrorType]], + inner_value: Callable[ + [_EnvType_contra], IOResult[_ValueType_co, _ErrorType] + ], ) -> None: """ Public constructor for this type. Also required for typing. @@ -131,7 +136,9 @@ def __init__( """ super().__init__(inner_value) - def __call__(self, deps: _EnvType) -> IOResult[_ValueType, _ErrorType]: + def __call__( + self, deps: _EnvType_contra + ) -> IOResult[_ValueType_co, _ErrorType]: """ Evaluates the wrapped function. @@ -156,7 +163,7 @@ def __call__(self, deps: _EnvType) -> IOResult[_ValueType, _ErrorType]: def swap( self, - ) -> RequiresContextIOResult[_ErrorType, _ValueType, _EnvType]: + ) -> RequiresContextIOResult[_ErrorType, _ValueType_co, _EnvType_contra]: """ Swaps value and error types. @@ -180,8 +187,9 @@ def swap( return RequiresContextIOResult(lambda deps: self(deps).swap()) def map( - self, function: Callable[[_ValueType], _NewValueType], - ) -> RequiresContextIOResult[_NewValueType, _ErrorType, _EnvType]: + self, + function: Callable[[_ValueType_co], _NewValueType], + ) -> RequiresContextIOResult[_NewValueType, _ErrorType, _EnvType_contra]: """ Composes successful container with a pure function. @@ -205,11 +213,11 @@ def apply( self, container: Kind3[ RequiresContextIOResult, - Callable[[_ValueType], _NewValueType], + Callable[[_ValueType_co], _NewValueType], _ErrorType, - _EnvType, + _EnvType_contra, ], - ) -> RequiresContextIOResult[_NewValueType, _ErrorType, _EnvType]: + ) -> RequiresContextIOResult[_NewValueType, _ErrorType, _EnvType_contra]: """ Calls a wrapped function in a container on this container. @@ -245,15 +253,15 @@ def apply( def bind( self, function: Callable[ - [_ValueType], + [_ValueType_co], Kind3[ RequiresContextIOResult, _NewValueType, _ErrorType, - _EnvType, + _EnvType_contra, ], ], - ) -> RequiresContextIOResult[_NewValueType, _ErrorType, _EnvType]: + ) -> RequiresContextIOResult[_NewValueType, _ErrorType, _EnvType_contra]: """ Composes this container with a function returning the same type. @@ -293,8 +301,8 @@ def bind( def bind_result( self, - function: Callable[[_ValueType], Result[_NewValueType, _ErrorType]], - ) -> RequiresContextIOResult[_NewValueType, _ErrorType, _EnvType]: + function: Callable[[_ValueType_co], Result[_NewValueType, _ErrorType]], + ) -> RequiresContextIOResult[_NewValueType, _ErrorType, _EnvType_contra]: """ Binds ``Result`` returning function to the current container. @@ -327,10 +335,10 @@ def bind_result( def bind_context( self, function: Callable[ - [_ValueType], - RequiresContext[_NewValueType, _EnvType], + [_ValueType_co], + RequiresContext[_NewValueType, _EnvType_contra], ], - ) -> RequiresContextIOResult[_NewValueType, _ErrorType, _EnvType]: + ) -> RequiresContextIOResult[_NewValueType, _ErrorType, _EnvType_contra]: """ Binds ``RequiresContext`` returning function to current container. @@ -362,10 +370,10 @@ def bind_context( def bind_context_result( self, function: Callable[ - [_ValueType], - RequiresContextResult[_NewValueType, _ErrorType, _EnvType], + [_ValueType_co], + RequiresContextResult[_NewValueType, _ErrorType, _EnvType_contra], ], - ) -> RequiresContextIOResult[_NewValueType, _ErrorType, _EnvType]: + ) -> RequiresContextIOResult[_NewValueType, _ErrorType, _EnvType_contra]: """ Binds ``RequiresContextResult`` returning function to the current one. @@ -414,8 +422,8 @@ def bind_context_result( def bind_io( self, - function: Callable[[_ValueType], IO[_NewValueType]], - ) -> RequiresContextIOResult[_NewValueType, _ErrorType, _EnvType]: + function: Callable[[_ValueType_co], IO[_NewValueType]], + ) -> RequiresContextIOResult[_NewValueType, _ErrorType, _EnvType_contra]: """ Binds ``IO`` returning function to the current container. @@ -442,8 +450,10 @@ def bind_io( def bind_ioresult( self, - function: Callable[[_ValueType], IOResult[_NewValueType, _ErrorType]], - ) -> RequiresContextIOResult[_NewValueType, _ErrorType, _EnvType]: + function: Callable[ + [_ValueType_co], IOResult[_NewValueType, _ErrorType] + ], + ) -> RequiresContextIOResult[_NewValueType, _ErrorType, _EnvType_contra]: """ Binds ``IOResult`` returning function to the current container. @@ -473,8 +483,9 @@ def bind_ioresult( ) def alt( - self, function: Callable[[_ErrorType], _NewErrorType], - ) -> RequiresContextIOResult[_ValueType, _NewErrorType, _EnvType]: + self, + function: Callable[[_ErrorType], _NewErrorType], + ) -> RequiresContextIOResult[_ValueType_co, _NewErrorType, _EnvType_contra]: """ Composes failed container with a pure function. @@ -500,12 +511,12 @@ def lash( [_ErrorType], Kind3[ RequiresContextIOResult, - _ValueType, + _ValueType_co, _NewErrorType, - _EnvType, + _EnvType_contra, ], ], - ) -> RequiresContextIOResult[_ValueType, _NewErrorType, _EnvType]: + ) -> RequiresContextIOResult[_ValueType_co, _NewErrorType, _EnvType_contra]: """ Composes this container with a function returning the same type. @@ -545,15 +556,15 @@ def lash( def compose_result( self, function: Callable[ - [Result[_ValueType, _ErrorType]], + [Result[_ValueType_co, _ErrorType]], Kind3[ RequiresContextIOResult, _NewValueType, _ErrorType, - _EnvType, + _EnvType_contra, ], ], - ) -> RequiresContextIOResult[_NewValueType, _ErrorType, _EnvType]: + ) -> RequiresContextIOResult[_NewValueType, _ErrorType, _EnvType_contra]: """ Composes inner ``Result`` with ``ReaderIOResult`` returning function. @@ -580,14 +591,14 @@ def compose_result( """ return RequiresContextIOResult( lambda deps: dekind( - function(self(deps)._inner_value), # noqa: WPS437 + function(self(deps)._inner_value), # noqa: SLF001 )(deps), ) def modify_env( self, - function: Callable[[_NewEnvType], _EnvType], - ) -> RequiresContextIOResult[_ValueType, _ErrorType, _NewEnvType]: + function: Callable[[_NewEnvType], _EnvType_contra], + ) -> RequiresContextIOResult[_ValueType_co, _ErrorType, _NewEnvType]: """ Allows to modify the environment type. @@ -608,7 +619,9 @@ def modify_env( return RequiresContextIOResult(lambda deps: self(function(deps))) @classmethod - def ask(cls) -> RequiresContextIOResult[_EnvType, _ErrorType, _EnvType]: + def ask( + cls, + ) -> RequiresContextIOResult[_EnvType_contra, _ErrorType, _EnvType_contra]: """ Is used to get the current dependencies inside the call stack. @@ -618,7 +631,7 @@ def ask(cls) -> RequiresContextIOResult[_EnvType, _ErrorType, _EnvType]: Please, refer to the docs there to learn how to use it. One important note that is worth duplicating here: - you might need to provide ``_EnvType`` explicitly, + you might need to provide ``_EnvType_contra`` explicitly, so ``mypy`` will know about it statically. .. code:: python @@ -634,7 +647,8 @@ def ask(cls) -> RequiresContextIOResult[_EnvType, _ErrorType, _EnvType]: @classmethod def from_result( - cls, inner_value: Result[_NewValueType, _NewErrorType], + cls, + inner_value: Result[_NewValueType, _NewErrorType], ) -> RequiresContextIOResult[_NewValueType, _NewErrorType, NoDeps]: """ Creates new container with ``Result`` as a unit value. @@ -705,7 +719,8 @@ def from_failed_io( @classmethod def from_ioresult( - cls, inner_value: IOResult[_NewValueType, _NewErrorType], + cls, + inner_value: IOResult[_NewValueType, _NewErrorType], ) -> RequiresContextIOResult[_NewValueType, _NewErrorType, NoDeps]: """ Creates new container with ``IOResult`` as a unit value. @@ -730,8 +745,7 @@ def from_ioresult( @classmethod def from_ioresult_context( cls, - inner_value: - ReaderIOResult[_NewValueType, _NewErrorType, _NewEnvType], + inner_value: ReaderIOResult[_NewValueType, _NewErrorType, _NewEnvType], ) -> ReaderIOResult[_NewValueType, _NewErrorType, _NewEnvType]: """ Creates new container with ``ReaderIOResult`` as a unit value. @@ -756,9 +770,10 @@ def from_ioresult_context( def from_typecast( cls, inner_value: RequiresContext[ - IOResult[_NewValueType, _NewErrorType], _EnvType, + IOResult[_NewValueType, _NewErrorType], + _EnvType_contra, ], - ) -> RequiresContextIOResult[_NewValueType, _NewErrorType, _EnvType]: + ) -> RequiresContextIOResult[_NewValueType, _NewErrorType, _EnvType_contra]: """ You might end up with ``RequiresContext[IOResult]`` as a value. @@ -785,7 +800,8 @@ def from_typecast( @classmethod def from_context( - cls, inner_value: RequiresContext[_NewValueType, _NewEnvType], + cls, + inner_value: RequiresContext[_NewValueType, _NewEnvType], ) -> RequiresContextIOResult[_NewValueType, Any, _NewEnvType]: """ Creates new container from ``RequiresContext`` as a success unit. @@ -806,7 +822,8 @@ def from_context( @classmethod def from_failed_context( - cls, inner_value: RequiresContext[_NewValueType, _NewEnvType], + cls, + inner_value: RequiresContext[_NewValueType, _NewEnvType], ) -> RequiresContextIOResult[Any, _NewValueType, _NewEnvType]: """ Creates new container from ``RequiresContext`` as a failure unit. @@ -829,7 +846,9 @@ def from_failed_context( def from_result_context( cls, inner_value: RequiresContextResult[ - _NewValueType, _NewErrorType, _NewEnvType, + _NewValueType, + _NewErrorType, + _NewEnvType, ], ) -> RequiresContextIOResult[_NewValueType, _NewErrorType, _NewEnvType]: """ @@ -898,7 +917,9 @@ def from_failure( #: Alias for a popular case when ``Result`` has ``Exception`` as error type. RequiresContextIOResultE: TypeAlias = RequiresContextIOResult[ - _ValueType, Exception, _EnvType, + _ValueType_co, + Exception, + _EnvType_contra, ] #: Alias to save you some typing. Uses original name from Haskell. @@ -906,5 +927,7 @@ def from_failure( #: Alias to save you some typing. Uses ``Exception`` as error type. ReaderIOResultE: TypeAlias = RequiresContextIOResult[ - _ValueType, Exception, _EnvType, + _ValueType_co, + Exception, + _EnvType_contra, ] diff --git a/returns/context/requires_context_result.py b/returns/context/requires_context_result.py index 285a5d37a..c835b87a7 100644 --- a/returns/context/requires_context_result.py +++ b/returns/context/requires_context_result.py @@ -13,13 +13,13 @@ from returns.context.requires_context import RequiresContext # Context: -_EnvType = TypeVar('_EnvType', contravariant=True) +_EnvType_contra = TypeVar('_EnvType_contra', contravariant=True) _NewEnvType = TypeVar('_NewEnvType') # Result: -_ValueType = TypeVar('_ValueType', covariant=True) +_ValueType_co = TypeVar('_ValueType_co', covariant=True) _NewValueType = TypeVar('_NewValueType') -_ErrorType = TypeVar('_ErrorType', covariant=True) +_ErrorType_co = TypeVar('_ErrorType_co', covariant=True) _NewErrorType = TypeVar('_NewErrorType') # Helpers: @@ -29,8 +29,12 @@ @final class RequiresContextResult( # type: ignore[type-var] BaseContainer, - SupportsKind3['RequiresContextResult', _ValueType, _ErrorType, _EnvType], - reader_result.ReaderResultBasedN[_ValueType, _ErrorType, _EnvType], + SupportsKind3[ + 'RequiresContextResult', _ValueType_co, _ErrorType_co, _EnvType_contra + ], + reader_result.ReaderResultBasedN[ + _ValueType_co, _ErrorType_co, _EnvType_contra + ], ): """ The ``RequiresContextResult`` combinator. @@ -95,14 +99,18 @@ class RequiresContextResult( # type: ignore[type-var] __slots__ = () #: This field has an extra 'RequiresContext' just because `mypy` needs it. - _inner_value: Callable[[_EnvType], Result[_ValueType, _ErrorType]] + _inner_value: Callable[ + [_EnvType_contra], Result[_ValueType_co, _ErrorType_co] + ] #: A convenient placeholder to call methods created by `.from_value()`. no_args: ClassVar[NoDeps] = object() def __init__( self, - inner_value: Callable[[_EnvType], Result[_ValueType, _ErrorType]], + inner_value: Callable[ + [_EnvType_contra], Result[_ValueType_co, _ErrorType_co] + ], ) -> None: """ Public constructor for this type. Also required for typing. @@ -120,7 +128,9 @@ def __init__( """ super().__init__(inner_value) - def __call__(self, deps: _EnvType) -> Result[_ValueType, _ErrorType]: + def __call__( + self, deps: _EnvType_contra + ) -> Result[_ValueType_co, _ErrorType_co]: """ Evaluates the wrapped function. @@ -143,7 +153,9 @@ def __call__(self, deps: _EnvType) -> Result[_ValueType, _ErrorType]: """ return self._inner_value(deps) - def swap(self) -> RequiresContextResult[_ErrorType, _ValueType, _EnvType]: + def swap( + self, + ) -> RequiresContextResult[_ErrorType_co, _ValueType_co, _EnvType_contra]: """ Swaps value and error types. @@ -167,8 +179,9 @@ def swap(self) -> RequiresContextResult[_ErrorType, _ValueType, _EnvType]: return RequiresContextResult(lambda deps: self(deps).swap()) def map( - self, function: Callable[[_ValueType], _NewValueType], - ) -> RequiresContextResult[_NewValueType, _ErrorType, _EnvType]: + self, + function: Callable[[_ValueType_co], _NewValueType], + ) -> RequiresContextResult[_NewValueType, _ErrorType_co, _EnvType_contra]: """ Composes successful container with a pure function. @@ -192,11 +205,11 @@ def apply( self, container: Kind3[ RequiresContextResult, - Callable[[_ValueType], _NewValueType], - _ErrorType, - _EnvType, + Callable[[_ValueType_co], _NewValueType], + _ErrorType_co, + _EnvType_contra, ], - ) -> RequiresContextResult[_NewValueType, _ErrorType, _EnvType]: + ) -> RequiresContextResult[_NewValueType, _ErrorType_co, _EnvType_contra]: """ Calls a wrapped function in a container on this container. @@ -228,15 +241,15 @@ def apply( def bind( self, function: Callable[ - [_ValueType], + [_ValueType_co], Kind3[ RequiresContextResult, _NewValueType, - _ErrorType, - _EnvType, + _ErrorType_co, + _EnvType_contra, ], ], - ) -> RequiresContextResult[_NewValueType, _ErrorType, _EnvType]: + ) -> RequiresContextResult[_NewValueType, _ErrorType_co, _EnvType_contra]: """ Composes this container with a function returning the same type. @@ -274,8 +287,10 @@ def bind( def bind_result( self, - function: Callable[[_ValueType], Result[_NewValueType, _ErrorType]], - ) -> RequiresContextResult[_NewValueType, _ErrorType, _EnvType]: + function: Callable[ + [_ValueType_co], Result[_NewValueType, _ErrorType_co] + ], + ) -> RequiresContextResult[_NewValueType, _ErrorType_co, _EnvType_contra]: """ Binds ``Result`` returning function to current container. @@ -305,10 +320,10 @@ def bind_result( def bind_context( self, function: Callable[ - [_ValueType], - RequiresContext[_NewValueType, _EnvType], + [_ValueType_co], + RequiresContext[_NewValueType, _EnvType_contra], ], - ) -> RequiresContextResult[_NewValueType, _ErrorType, _EnvType]: + ) -> RequiresContextResult[_NewValueType, _ErrorType_co, _EnvType_contra]: """ Binds ``RequiresContext`` returning function to current container. @@ -338,8 +353,9 @@ def bind_context( ) def alt( - self, function: Callable[[_ErrorType], _NewErrorType], - ) -> RequiresContextResult[_ValueType, _NewErrorType, _EnvType]: + self, + function: Callable[[_ErrorType_co], _NewErrorType], + ) -> RequiresContextResult[_ValueType_co, _NewErrorType, _EnvType_contra]: """ Composes failed container with a pure function. @@ -362,15 +378,15 @@ def alt( def lash( self, function: Callable[ - [_ErrorType], + [_ErrorType_co], Kind3[ RequiresContextResult, - _ValueType, + _ValueType_co, _NewErrorType, - _EnvType, + _EnvType_contra, ], ], - ) -> RequiresContextResult[_ValueType, _NewErrorType, _EnvType]: + ) -> RequiresContextResult[_ValueType_co, _NewErrorType, _EnvType_contra]: """ Composes this container with a function returning the same type. @@ -407,8 +423,8 @@ def lash( def modify_env( self, - function: Callable[[_NewEnvType], _EnvType], - ) -> RequiresContextResult[_ValueType, _ErrorType, _NewEnvType]: + function: Callable[[_NewEnvType], _EnvType_contra], + ) -> RequiresContextResult[_ValueType_co, _ErrorType_co, _NewEnvType]: """ Allows to modify the environment type. @@ -429,7 +445,9 @@ def modify_env( return RequiresContextResult(lambda deps: self(function(deps))) @classmethod - def ask(cls) -> RequiresContextResult[_EnvType, _ErrorType, _EnvType]: + def ask( + cls, + ) -> RequiresContextResult[_EnvType_contra, _ErrorType_co, _EnvType_contra]: """ Is used to get the current dependencies inside the call stack. @@ -439,7 +457,7 @@ def ask(cls) -> RequiresContextResult[_EnvType, _ErrorType, _EnvType]: Please, refer to the docs there to learn how to use it. One important note that is worth duplicating here: - you might need to provide ``_EnvType`` explicitly, + you might need to provide ``_EnvType_contra`` explicitly, so ``mypy`` will know about it statically. .. code:: python @@ -455,7 +473,8 @@ def ask(cls) -> RequiresContextResult[_EnvType, _ErrorType, _EnvType]: @classmethod def from_result( - cls, inner_value: Result[_NewValueType, _NewErrorType], + cls, + inner_value: Result[_NewValueType, _NewErrorType], ) -> RequiresContextResult[_NewValueType, _NewErrorType, NoDeps]: """ Creates new container with ``Result`` as a unit value. @@ -481,9 +500,10 @@ def from_result( def from_typecast( cls, inner_value: RequiresContext[ - Result[_NewValueType, _NewErrorType], _EnvType, + Result[_NewValueType, _NewErrorType], + _EnvType_contra, ], - ) -> RequiresContextResult[_NewValueType, _NewErrorType, _EnvType]: + ) -> RequiresContextResult[_NewValueType, _NewErrorType, _EnvType_contra]: """ You might end up with ``RequiresContext[Result[...]]`` as a value. @@ -510,7 +530,8 @@ def from_typecast( @classmethod def from_context( - cls, inner_value: RequiresContext[_NewValueType, _NewEnvType], + cls, + inner_value: RequiresContext[_NewValueType, _NewEnvType], ) -> RequiresContextResult[_NewValueType, Any, _NewEnvType]: """ Creates new container from ``RequiresContext`` as a success unit. @@ -528,7 +549,8 @@ def from_context( @classmethod def from_failed_context( - cls, inner_value: RequiresContext[_NewValueType, _NewEnvType], + cls, + inner_value: RequiresContext[_NewValueType, _NewEnvType], ) -> RequiresContextResult[Any, _NewValueType, _NewEnvType]: """ Creates new container from ``RequiresContext`` as a failure unit. @@ -548,7 +570,9 @@ def from_failed_context( def from_result_context( cls, inner_value: RequiresContextResult[ - _NewValueType, _NewErrorType, _NewEnvType, + _NewValueType, + _NewErrorType, + _NewEnvType, ], ) -> RequiresContextResult[_NewValueType, _NewErrorType, _NewEnvType]: """ @@ -572,7 +596,8 @@ def from_result_context( @classmethod def from_value( - cls, inner_value: _FirstType, + cls, + inner_value: _FirstType, ) -> RequiresContextResult[_FirstType, Any, NoDeps]: """ Creates new container with ``Success(inner_value)`` as a unit value. @@ -588,7 +613,8 @@ def from_value( @classmethod def from_failure( - cls, inner_value: _FirstType, + cls, + inner_value: _FirstType, ) -> RequiresContextResult[Any, _FirstType, NoDeps]: """ Creates new container with ``Failure(inner_value)`` as a unit value. @@ -607,7 +633,9 @@ def from_failure( #: Alias for a popular case when ``Result`` has ``Exception`` as error type. RequiresContextResultE: TypeAlias = RequiresContextResult[ - _ValueType, Exception, _EnvType, + _ValueType_co, + Exception, + _EnvType_contra, ] #: Alias to save you some typing. Uses original name from Haskell. @@ -615,5 +643,7 @@ def from_failure( #: Alias to save you some typing. Has ``Exception`` as error type. ReaderResultE: TypeAlias = RequiresContextResult[ - _ValueType, Exception, _EnvType, + _ValueType_co, + Exception, + _EnvType_contra, ] diff --git a/returns/contrib/hypothesis/_entrypoint.py b/returns/contrib/hypothesis/_entrypoint.py index 8d2351117..d611eb455 100644 --- a/returns/contrib/hypothesis/_entrypoint.py +++ b/returns/contrib/hypothesis/_entrypoint.py @@ -20,27 +20,29 @@ def _setup_hook() -> None: - from hypothesis import strategies as st + from hypothesis import strategies as st # noqa: PLC0415 - from returns.context import ( + from returns.context import ( # noqa: PLC0415 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 + from returns.future import Future, FutureResult # noqa: PLC0415 + from returns.io import IO, IOResult # noqa: PLC0415 + from returns.maybe import Maybe # noqa: PLC0415 + from returns.result import Result # noqa: PLC0415 def factory( container_type: type[_Inst], ) -> Callable[[Any], st.SearchStrategy[_Inst]]: def decorator(thing: Any) -> st.SearchStrategy[_Inst]: - from returns.contrib.hypothesis.containers import ( + from returns.contrib.hypothesis.containers import ( # noqa: PLC0415 strategy_from_container, ) + return strategy_from_container(container_type)(thing) + return decorator #: Our types that we register in hypothesis diff --git a/returns/contrib/hypothesis/containers.py b/returns/contrib/hypothesis/containers.py index 0842b5dfc..949beecb8 100644 --- a/returns/contrib/hypothesis/containers.py +++ b/returns/contrib/hypothesis/containers.py @@ -32,8 +32,8 @@ def strategy_from_container( will produce any value for success cases and only exceptions for failure cases. """ - from returns.interfaces.applicative import ApplicativeN - from returns.interfaces.specific import maybe, result + from returns.interfaces.applicative import ApplicativeN # noqa: PLC0415 + from returns.interfaces.specific import maybe, result # noqa: PLC0415 def factory(type_: type) -> st.SearchStrategy: value_type, error_type = _get_type_vars(type_) @@ -42,21 +42,28 @@ def factory(type_: type) -> st.SearchStrategy: if use_init and getattr(container_type, '__init__', None): strategies.append(st.builds(container_type)) if issubclass(container_type, ApplicativeN): - strategies.append(st.builds( - container_type.from_value, - st.from_type(value_type), - )) + strategies.append( + st.builds( + container_type.from_value, + st.from_type(value_type), + ) + ) if issubclass(container_type, result.ResultLikeN): - strategies.append(st.builds( - container_type.from_failure, - st.from_type(error_type), - )) + strategies.append( + st.builds( + container_type.from_failure, + st.from_type(error_type), + ) + ) if issubclass(container_type, maybe.MaybeLikeN): - strategies.append(st.builds( - container_type.from_optional, - st.from_type(value_type), - )) + strategies.append( + st.builds( + container_type.from_optional, + st.from_type(value_type), + ) + ) return st.one_of(*strategies) + return factory diff --git a/returns/contrib/hypothesis/laws.py b/returns/contrib/hypothesis/laws.py index eaab28e40..273543e4d 100644 --- a/returns/contrib/hypothesis/laws.py +++ b/returns/contrib/hypothesis/laws.py @@ -7,7 +7,7 @@ from hypothesis import given from hypothesis import settings as hypothesis_settings from hypothesis import strategies as st -from hypothesis.strategies._internal import types +from hypothesis.strategies._internal import types # noqa: PLC2701 from returns.contrib.hypothesis.containers import strategy_from_container from returns.primitives.laws import Law, Lawful @@ -54,7 +54,7 @@ def check_all_laws( """ settings = _Settings( - settings_kwargs if settings_kwargs is not None else {}, + settings_kwargs or {}, use_init, ) @@ -87,12 +87,8 @@ def container_strategies( base_type for base_type in container_type.__mro__ if ( - getattr(base_type, '__module__', '').startswith('returns.') and - # We don't register `Lawful` type, it is not a container: - base_type != Lawful and - # We will register the container itself later with - # `maybe_register_container` function: - base_type != container_type + getattr(base_type, '__module__', '').startswith('returns.') + and base_type not in {Lawful, container_type} ) } for interface in our_interfaces: @@ -108,7 +104,7 @@ def container_strategies( yield finally: for interface in our_interfaces: - types._global_type_lookup.pop(interface) + types._global_type_lookup.pop(interface) # noqa: SLF001 _clean_caches() @@ -119,7 +115,7 @@ def register_container( use_init: bool, ) -> Iterator[None]: """Temporary registers a container if it is not registered yet.""" - used = types._global_type_lookup.pop(container_type, None) + used = types._global_type_lookup.pop(container_type, None) # noqa: SLF001 st.register_type_strategy( container_type, strategy_from_container( @@ -131,7 +127,7 @@ def register_container( try: yield finally: - types._global_type_lookup.pop(container_type) + types._global_type_lookup.pop(container_type) # noqa: SLF001 if used: st.register_type_strategy(container_type, used) else: @@ -145,6 +141,7 @@ def pure_functions() -> Iterator[None]: It is not a default in ``hypothesis``. """ + def factory(thing) -> st.SearchStrategy: like = ( (lambda: None) @@ -155,20 +152,18 @@ def factory(thing) -> st.SearchStrategy: return st.functions( like=like, returns=st.from_type( - return_type - if return_type is not None - else type(None), + type(None) if return_type is None else return_type, ), pure=True, ) - used = types._global_type_lookup[Callable] # type: ignore[index] + used = types._global_type_lookup[Callable] # type: ignore[index] # noqa: SLF001 st.register_type_strategy(Callable, factory) # type: ignore[arg-type] try: yield finally: - types._global_type_lookup.pop(Callable) # type: ignore[call-overload] + types._global_type_lookup.pop(Callable) # type: ignore[call-overload] # noqa: SLF001 st.register_type_strategy(Callable, used) # type: ignore[arg-type] @@ -184,18 +179,19 @@ def type_vars() -> Iterator[None]: for example, ``nan`` does not work for us """ + def factory(thing): return types.resolve_TypeVar(thing).filter( - lambda inner: inner == inner, # noqa: WPS312 + lambda inner: inner == inner, # noqa: PLR0124, WPS312 ) - used = types._global_type_lookup.pop(TypeVar) + used = types._global_type_lookup.pop(TypeVar) # noqa: SLF001 st.register_type_strategy(TypeVar, factory) try: yield finally: - types._global_type_lookup.pop(TypeVar) + types._global_type_lookup.pop(TypeVar) # noqa: SLF001 st.register_type_strategy(TypeVar, used) @@ -207,13 +203,15 @@ def clean_plugin_context() -> Iterator[None]: Otherwise, some types might be messed up. """ saved_stategies = {} - for strategy_key, strategy in types._global_type_lookup.items(): - if isinstance(strategy_key, type): - if strategy_key.__module__.startswith('returns.'): - saved_stategies.update({strategy_key: strategy}) + for strategy_key, strategy in types._global_type_lookup.items(): # noqa: SLF001 + if isinstance( # type: ignore[redundant-expr] + strategy_key, + type, + ) and strategy_key.__module__.startswith('returns.'): + saved_stategies.update({strategy_key: strategy}) for key_to_remove in saved_stategies: - types._global_type_lookup.pop(key_to_remove) + types._global_type_lookup.pop(key_to_remove) # noqa: SLF001 _clean_caches() try: @@ -224,7 +222,7 @@ def clean_plugin_context() -> Iterator[None]: def _clean_caches() -> None: - st.from_type.__clear_cache() # type: ignore[attr-defined] + st.from_type.__clear_cache() # type: ignore[attr-defined] # noqa: SLF001 def _run_law( @@ -245,6 +243,7 @@ def factory(source: st.DataObject) -> None: register_container(container_type, use_init=settings.use_init), ) source.draw(st.builds(law.definition)) + return factory diff --git a/returns/contrib/mypy/_consts.py b/returns/contrib/mypy/_consts.py index 3745247f0..d5db58f12 100644 --- a/returns/contrib/mypy/_consts.py +++ b/returns/contrib/mypy/_consts.py @@ -18,7 +18,7 @@ #: Used for HKT emulation. TYPED_KINDN: Final = 'returns.primitives.hkt.KindN' -TYPED_KINDN_ACCESS: Final = '{0}.'.format(TYPED_KINDN) +TYPED_KINDN_ACCESS: Final = f'{TYPED_KINDN}.' TYPED_KIND_DEKIND: Final = 'returns.primitives.hkt.dekind' TYPED_KIND_KINDED_CALL: Final = 'returns.primitives.hkt.Kinded.__call__' TYPED_KIND_KINDED_GET: Final = 'returns.primitives.hkt.Kinded.__get__' @@ -29,7 +29,6 @@ 'returns.io.IO.do', 'returns.maybe.Maybe.do', 'returns.future.Future.do', - # Also infer error types: 'returns.result.Result.do', 'returns.io.IOResult.do', diff --git a/returns/contrib/mypy/_features/curry.py b/returns/contrib/mypy/_features/curry.py index b74988e58..5feb55065 100644 --- a/returns/contrib/mypy/_features/curry.py +++ b/returns/contrib/mypy/_features/curry.py @@ -5,9 +5,15 @@ from mypy.nodes import ARG_STAR, ARG_STAR2 from mypy.plugin import FunctionContext -from mypy.types import AnyType, CallableType, FunctionLike, Overloaded +from mypy.types import ( + AnyType, + CallableType, + FunctionLike, + Overloaded, + TypeOfAny, + get_proper_type, +) from mypy.types import Type as MypyType -from mypy.types import TypeOfAny, get_proper_type from returns.contrib.mypy._structures.args import FuncArg from returns.contrib.mypy._typeops.transform_callable import ( @@ -37,7 +43,7 @@ class _ArgTree: def __init__(self, case: CallableType | None) -> None: self.case = case - self.children: list['_ArgTree'] = [] + self.children: list[_ArgTree] = [] @final @@ -70,7 +76,8 @@ def __init__(self, original: CallableType, ctx: FunctionContext) -> None: # Because, otherwise `detach_callable` with add # unused variables to intermediate callables. self._default = cast( - CallableType, self._ctx.default_return_type, + CallableType, + self._ctx.default_return_type, ).copy_modified( ret_type=AnyType(TypeOfAny.implementation_artifact), ) @@ -111,6 +118,7 @@ def _build_argtree( Arguments that have more than one child are treated as overloads. """ + def factory( args: _RawArgTree, ) -> Iterator[tuple[list[FuncArg], _RawArgTree]]: @@ -133,14 +141,17 @@ def _build_overloads_from_argtree(self, argtree: _ArgTree) -> None: """Generates functions from argument tree.""" for child in argtree.children: self._build_overloads_from_argtree(child) - assert child.case # mypy is not happy # noqa: S101 + assert child.case # mypy is not happy if not child.children: child.case = Intermediate(child.case).with_ret_type( self._original.ret_type, ) - if argtree.case is not None: + if argtree.case is None: + # Root is reached, we need to save the result: + self._overloads.append(child.case) + else: # We need to go backwards and to replace the return types # of the previous functions. Like so: # 1. `def x -> A` @@ -149,16 +160,21 @@ def _build_overloads_from_argtree(self, argtree: _ArgTree) -> None: # Will result in `def x -> y -> A` # We also overloadify existing return types. ret_type = get_proper_type(argtree.case.ret_type) - temp_any = isinstance( - ret_type, AnyType, - ) and ret_type.type_of_any == TypeOfAny.implementation_artifact + temp_any = ( + isinstance( + ret_type, + AnyType, + ) + and ret_type.type_of_any + == TypeOfAny.implementation_artifact + ) argtree.case = Intermediate(argtree.case).with_ret_type( - child.case if temp_any else Overloaded( + child.case + if temp_any + else Overloaded( [child.case, *cast(FunctionLike, ret_type).items], ), ) - else: # Root is reached, we need to save the result: - self._overloads.append(child.case) def _slices(self, source: list[FuncArg]) -> Iterator[list[list[FuncArg]]]: """ diff --git a/returns/contrib/mypy/_features/do_notation.py b/returns/contrib/mypy/_features/do_notation.py index 7ff3958ff..c23230bde 100644 --- a/returns/contrib/mypy/_features/do_notation.py +++ b/returns/contrib/mypy/_features/do_notation.py @@ -5,9 +5,15 @@ from mypy.plugin import MethodContext from mypy.subtypes import is_subtype from mypy.typeops import make_simplified_union -from mypy.types import AnyType, CallableType, Instance +from mypy.types import ( + AnyType, + CallableType, + Instance, + TypeOfAny, + UnionType, + get_proper_type, +) from mypy.types import Type as MypyType -from mypy.types import TypeOfAny, UnionType, get_proper_type _INVALID_DO_NOTATION_SOURCE: Final = ( 'Invalid type supplied in do-notation: expected "{0}", got "{1}"' diff --git a/returns/contrib/mypy/_features/flow.py b/returns/contrib/mypy/_features/flow.py index ce814e977..21d0bd23b 100644 --- a/returns/contrib/mypy/_features/flow.py +++ b/returns/contrib/mypy/_features/flow.py @@ -42,7 +42,7 @@ def analyze(ctx: FunctionContext) -> MypyType: # because for some reason, `mypy` does not do it correctly. # It inferes `covariant` types incorrectly. real_arg_types = tuple( - ctx.api.expr_checker.accept(arg) # type: ignore + ctx.api.expr_checker.accept(arg) # type: ignore for arg in ctx.args[1] ) diff --git a/returns/contrib/mypy/_features/kind.py b/returns/contrib/mypy/_features/kind.py index 29eadc2ef..a14185d54 100644 --- a/returns/contrib/mypy/_features/kind.py +++ b/returns/contrib/mypy/_features/kind.py @@ -9,9 +9,18 @@ MethodSigContext, ) from mypy.typeops import bind_self -from mypy.types import AnyType, CallableType, FunctionLike, Instance, Overloaded +from mypy.types import ( + AnyType, + CallableType, + FunctionLike, + Instance, + Overloaded, + TypeOfAny, + TypeType, + TypeVarType, + get_proper_type, +) from mypy.types import Type as MypyType -from mypy.types import TypeOfAny, TypeType, TypeVarType, get_proper_type from returns.contrib.mypy._typeops.fallback import asserts_fallback_to_any from returns.contrib.mypy._typeops.visitor import translate_kind_instance @@ -164,4 +173,4 @@ def _crop_kind_args( """Returns the correct amount of type arguments for a kind.""" if limit is None: limit = kind.args[0].args # type: ignore - return kind.args[1:len(limit) + 1] + return kind.args[1 : len(limit) + 1] diff --git a/returns/contrib/mypy/_features/partial.py b/returns/contrib/mypy/_features/partial.py index 50c3069aa..9d24489a3 100644 --- a/returns/contrib/mypy/_features/partial.py +++ b/returns/contrib/mypy/_features/partial.py @@ -1,4 +1,5 @@ from collections.abc import Iterator +from itertools import starmap from typing import Final, final from mypy.nodes import ARG_STAR, ARG_STAR2 @@ -56,14 +57,14 @@ def analyze(ctx: FunctionContext) -> ProperType: if len(list(filter(len, ctx.arg_types))) == 1: return function_def # this means, that `partial(func)` is called - elif not isinstance(function_def, _SUPPORTED_TYPES): + if not isinstance(function_def, _SUPPORTED_TYPES): return default_return - elif isinstance(function_def, (Instance, TypeType)): + if isinstance(function_def, Instance | TypeType): # We force `Instance` and similar types to coercse to callable: function_def = func_args.get_callable_from_context() is_valid, applied_args = func_args.build_from_context() - if not isinstance(function_def, (CallableType, Overloaded)) or not is_valid: + if not isinstance(function_def, CallableType | Overloaded) or not is_valid: return default_return return _PartialFunctionReducer( @@ -226,14 +227,17 @@ def __init__(self, function_ctx: FunctionContext) -> None: self._function_ctx.arg_names[1:], self._function_ctx.arg_types[1:], self._function_ctx.arg_kinds[1:], + strict=False, ) def get_callable_from_context(self) -> ProperType: """Returns callable type from the context.""" - return get_proper_type(safe_translate_to_function( - self._function_ctx.arg_types[0][0], - self._function_ctx, - )) + return get_proper_type( + safe_translate_to_function( + self._function_ctx.arg_types[0][0], + self._function_ctx, + ) + ) def build_from_context(self) -> tuple[bool, list[FuncArg]]: """ @@ -252,7 +256,9 @@ def build_from_context(self) -> tuple[bool, list[FuncArg]]: """ applied_args = [] for names, types, kinds in self._parts: - for arg in self._generate_applied_args(zip(names, types, kinds)): + for arg in self._generate_applied_args( + zip(names, types, kinds, strict=False) + ): if arg.kind in {ARG_STAR, ARG_STAR2}: # We cannot really work with `*args`, `**kwargs`. return False, [] @@ -261,7 +267,4 @@ def build_from_context(self) -> tuple[bool, list[FuncArg]]: return True, applied_args def _generate_applied_args(self, arg_parts) -> Iterator[FuncArg]: - yield from ( - FuncArg(name, typ, kind) - for name, typ, kind in arg_parts - ) + yield from starmap(FuncArg, arg_parts) diff --git a/returns/contrib/mypy/_features/pipe.py b/returns/contrib/mypy/_features/pipe.py index eb78fe4dd..1ab7bf1f4 100644 --- a/returns/contrib/mypy/_features/pipe.py +++ b/returns/contrib/mypy/_features/pipe.py @@ -36,13 +36,23 @@ >>> assert pipeline(0) == 'not bigger' # `signature and `infer` again """ + from collections.abc import Callable from mypy.nodes import ARG_POS from mypy.plugin import FunctionContext, MethodContext, MethodSigContext -from mypy.types import AnyType, CallableType, FunctionLike, Instance, ProperType +from mypy.types import ( + AnyType, + CallableType, + FunctionLike, + Instance, + ProperType, + TypeOfAny, + UnionType, + get_proper_type, + get_proper_types, +) from mypy.types import Type as MypyType -from mypy.types import TypeOfAny, UnionType, get_proper_type, get_proper_types from returns.contrib.mypy._typeops.analtype import translate_to_function from returns.contrib.mypy._typeops.inference import PipelineInference @@ -109,10 +119,7 @@ def _unify_type( function: FunctionLike, fetch_type: Callable[[CallableType], MypyType], ) -> MypyType: - return UnionType.make_union([ - fetch_type(case) - for case in function.items - ]) + return UnionType.make_union([fetch_type(case) for case in function.items]) def _get_pipeline_def( diff --git a/returns/contrib/mypy/_structures/args.py b/returns/contrib/mypy/_structures/args.py index 9f5988072..45c00c262 100644 --- a/returns/contrib/mypy/_structures/args.py +++ b/returns/contrib/mypy/_structures/args.py @@ -1,22 +1,23 @@ -from collections import namedtuple -from typing import final +from itertools import starmap +from typing import NamedTuple, final from mypy.nodes import ArgKind, Context, TempNode from mypy.types import CallableType from mypy.types import Type as MypyType -#: Basic struct to represent function arguments. -_FuncArgStruct = namedtuple('_FuncArgStruct', ('name', 'type', 'kind')) - -@final -class FuncArg(_FuncArgStruct): - """Representation of function arg with all required fields and methods.""" +class _FuncArgStruct(NamedTuple): + """Basic struct to represent function arguments.""" name: str | None type: MypyType # noqa: WPS125 kind: ArgKind + +@final +class FuncArg(_FuncArgStruct): + """Representation of function arg with all required fields and methods.""" + def expression(self, context: Context) -> TempNode: """Hack to pass unexisting `Expression` to typechecker.""" return TempNode(self.type, context=context) @@ -28,5 +29,6 @@ def from_callable(cls, function_def: CallableType) -> list['FuncArg']: function_def.arg_names, function_def.arg_types, function_def.arg_kinds, + strict=False, ) - return [cls(*part) for part in parts] + return list(starmap(cls, parts)) diff --git a/returns/contrib/mypy/_structures/types.py b/returns/contrib/mypy/_structures/types.py index df9a004fd..5e1ea109c 100644 --- a/returns/contrib/mypy/_structures/types.py +++ b/returns/contrib/mypy/_structures/types.py @@ -1,9 +1,6 @@ -from typing import Union +from typing import TypeAlias from mypy.plugin import FunctionContext, MethodContext #: We treat them equally when working with functions or methods. -CallableContext = Union[ - FunctionContext, - MethodContext, -] +CallableContext: TypeAlias = FunctionContext | MethodContext diff --git a/returns/contrib/mypy/_typeops/analtype.py b/returns/contrib/mypy/_typeops/analtype.py index d8ce126ae..9b7c845a1 100644 --- a/returns/contrib/mypy/_typeops/analtype.py +++ b/returns/contrib/mypy/_typeops/analtype.py @@ -3,9 +3,8 @@ from mypy.checkmember import analyze_member_access from mypy.nodes import ARG_NAMED, ARG_OPT -from mypy.types import CallableType, FunctionLike, ProperType +from mypy.types import CallableType, FunctionLike, ProperType, get_proper_type from mypy.types import Type as MypyType -from mypy.types import get_proper_type from returns.contrib.mypy._structures.args import FuncArg from returns.contrib.mypy._structures.types import CallableContext @@ -26,8 +25,7 @@ def analyze_call( ctx: CallableContext, *, show_errors: Literal[True], -) -> CallableType: - """Case when errors are reported and we cannot get ``None``.""" +) -> CallableType: ... @overload @@ -37,8 +35,7 @@ def analyze_call( ctx: CallableContext, *, show_errors: bool, -) -> CallableType | None: - """Errors are not reported, we can get ``None`` when errors happen.""" +) -> CallableType | None: ... def analyze_call(function, args, ctx, *, show_errors): @@ -53,7 +50,7 @@ def analyze_call(function, args, ctx, *, show_errors): """ checker = ctx.api.expr_checker with checker.msg.filter_errors(save_filtered_errors=True) as local_errors: - return_type, checked_function = checker.check_call( + _return_type, checked_function = checker.check_call( function, [arg.expression(ctx.context) for arg in args], [_KIND_MAPPING.get(arg.kind, arg.kind) for arg in args], @@ -93,7 +90,11 @@ def safe_translate_to_function( checker = ctx.api.expr_checker # type: ignore with checker.msg.filter_errors(): _return_type, function_def = checker.check_call( - function_def, [], [], ctx.context, [], + function_def, + [], + [], + ctx.context, + [], ) return function_def @@ -109,15 +110,17 @@ def translate_to_function( This also preserves all type arguments as-is. """ checker = ctx.api.expr_checker # type: ignore - return get_proper_type(analyze_member_access( - '__call__', - function_def, - ctx.context, - is_lvalue=False, - is_super=False, - is_operator=True, - msg=checker.msg, - original_type=function_def, - chk=checker.chk, - in_literal_context=checker.is_literal_context(), - )) + return get_proper_type( + analyze_member_access( + '__call__', + function_def, + ctx.context, + is_lvalue=False, + is_super=False, + is_operator=True, + msg=checker.msg, + original_type=function_def, + chk=checker.chk, + in_literal_context=checker.is_literal_context(), + ) + ) diff --git a/returns/contrib/mypy/_typeops/fallback.py b/returns/contrib/mypy/_typeops/fallback.py index 12941da5a..098638473 100644 --- a/returns/contrib/mypy/_typeops/fallback.py +++ b/returns/contrib/mypy/_typeops/fallback.py @@ -18,6 +18,7 @@ def asserts_fallback_to_any(function: _CallableType) -> _CallableType: just return ``Any`` and hope that someday someone reports it. """ + @wraps(function) def decorator(*args, **kwargs): try: @@ -25,4 +26,5 @@ def decorator(*args, **kwargs): except AssertionError: # TODO: log it somehow return AnyType(TypeOfAny.implementation_artifact) + return decorator # type: ignore diff --git a/returns/contrib/mypy/_typeops/inference.py b/returns/contrib/mypy/_typeops/inference.py index 8b9153750..bc713ebe2 100644 --- a/returns/contrib/mypy/_typeops/inference.py +++ b/returns/contrib/mypy/_typeops/inference.py @@ -6,9 +6,14 @@ from mypy.expandtype import expand_type from mypy.nodes import ARG_POS, ArgKind from mypy.plugin import FunctionContext -from mypy.types import CallableType, FunctionLike, ProperType +from mypy.types import ( + CallableType, + FunctionLike, + ProperType, + TypeVarId, + get_proper_type, +) from mypy.types import Type as MypyType -from mypy.types import TypeVarId, get_proper_type from returns.contrib.mypy._structures.args import FuncArg from returns.contrib.mypy._structures.types import CallableContext @@ -50,7 +55,7 @@ def __init__( """ self._case_function = case_function - self._fallback = fallback if fallback else self._case_function + self._fallback = fallback or self._case_function self._ctx = ctx def from_usage( @@ -68,10 +73,7 @@ def _infer_constraints( """Creates mapping of ``typevar`` to real type that we already know.""" checker = self._ctx.api.expr_checker # type: ignore kinds = [arg.kind for arg in applied_args] - exprs = [ - arg.expression(self._ctx.context) - for arg in applied_args - ] + exprs = [arg.expression(self._ctx.context) for arg in applied_args] formal_to_actual = map_actuals_to_formals( kinds, @@ -89,8 +91,7 @@ def _infer_constraints( context=checker.argument_infer_context(), ) return { - constraint.type_var: constraint.target - for constraint in constraints + constraint.type_var: constraint.target for constraint in constraints } @@ -117,7 +118,7 @@ def from_callable_sequence( parameter = FuncArg(None, self._instance, ARG_POS) ret_type = get_proper_type(ctx.default_return_type) - for pipeline, kind in zip(pipeline_types, pipeline_kinds): + for pipeline, kind in zip(pipeline_types, pipeline_kinds, strict=False): ret_type = self._proper_type( analyze_call( cast(FunctionLike, pipeline), diff --git a/returns/contrib/mypy/_typeops/transform_callable.py b/returns/contrib/mypy/_typeops/transform_callable.py index 7909176d5..4b41cc022 100644 --- a/returns/contrib/mypy/_typeops/transform_callable.py +++ b/returns/contrib/mypy/_typeops/transform_callable.py @@ -2,9 +2,15 @@ from mypy.nodes import ARG_OPT, ARG_POS, ARG_STAR, ARG_STAR2, ArgKind from mypy.typeops import get_type_vars -from mypy.types import AnyType, CallableType, FunctionLike, Overloaded +from mypy.types import ( + AnyType, + CallableType, + FunctionLike, + Overloaded, + TypeOfAny, + TypeVarType, +) from mypy.types import Type as MypyType -from mypy.types import TypeOfAny, TypeVarType from returns.contrib.mypy._structures.args import FuncArg @@ -50,11 +56,13 @@ def with_applied_args(self, applied_args: list[FuncArg]) -> CallableType: def with_signature(self, new_args: list[FuncArg]) -> CallableType: """Smartly creates a new callable from a given arguments.""" - return detach_callable(self._case_function.copy_modified( - arg_names=[arg.name for arg in new_args], - arg_types=[arg.type for arg in new_args], - arg_kinds=[arg.kind for arg in new_args], - )) + return detach_callable( + self._case_function.copy_modified( + arg_names=[arg.name for arg in new_args], + arg_types=[arg.type for arg in new_args], + arg_kinds=[arg.kind for arg in new_args], + ) + ) def with_ret_type(self, ret_type: MypyType) -> CallableType: """Smartly creates a new callable from a given return type.""" @@ -64,10 +72,13 @@ def _applied_positional_args( self, applied_args: list[FuncArg], ) -> list[FuncArg]: - callee_args = list(filter( - lambda name: name.name is None, # TODO: maybe use `kind` instead? - applied_args, - )) + callee_args = list( + filter( + lambda name: name.name + is None, # TODO: maybe use `kind` instead? + applied_args, + ) + ) new_function_args = [] for ind, arg in enumerate(FuncArg.from_callable(self._case_function)): @@ -79,10 +90,12 @@ def _applied_named_args( self, applied_args: list[FuncArg], ) -> list[FuncArg]: - callee_args = list(filter( - lambda name: name.name is not None, - applied_args, - )) + callee_args = list( + filter( + lambda name: name.name is not None, + applied_args, + ) + ) new_function_args = [] for arg in FuncArg.from_callable(self._case_function): @@ -117,22 +130,24 @@ def __init__( def diff(self) -> CallableType: """Finds a diff between two functions' arguments.""" intermediate_names = [ - arg.name - for arg in FuncArg.from_callable(self._intermediate) + arg.name for arg in FuncArg.from_callable(self._intermediate) ] new_function_args = [] for index, arg in enumerate(FuncArg.from_callable(self._original)): should_be_copied = ( - arg.kind in {ARG_STAR, ARG_STAR2} or - arg.name not in intermediate_names or + arg.kind in {ARG_STAR, ARG_STAR2} + or arg.name not in intermediate_names + or # We need to treat unnamed args differently, because python3.8 # has pos_only_args, all their names are `None`. # This is also true for `lambda` functions where `.name` # might be missing for some reason. ( - not arg.name and not ( - index < len(intermediate_names) and + not arg.name + and not ( + index < len(intermediate_names) + and # If this is also unnamed arg, then ignoring it. not intermediate_names[index] ) @@ -147,7 +162,7 @@ def diff(self) -> CallableType: # TODO: Remove this function once `mypy` order the TypeVars # by their appearance sequence -def detach_callable(typ: CallableType) -> CallableType: # noqa: C901, WPS210 +def detach_callable(typ: CallableType) -> CallableType: # noqa: WPS210 """ THIS IS A COPY OF `mypy.checker.detach_callable` FUNCTION. @@ -155,7 +170,7 @@ def detach_callable(typ: CallableType) -> CallableType: # noqa: C901, WPS210 TYPE VARIABLES! AS YOU CAN SEE, WE ORDER THE TYPE VARS BY THEIR APPEARANCE SEQUENCE. """ - type_list = typ.arg_types + [typ.ret_type] + type_list = [*typ.arg_types, typ.ret_type] appear_map: dict[str, list[int]] = {} for idx, inner_type in enumerate(type_list): @@ -165,9 +180,7 @@ def detach_callable(typ: CallableType) -> CallableType: # noqa: C901, WPS210 appear_map[var.fullname] = [] appear_map[var.fullname].append(idx) - used_type_var_names = set() - for var_name, _ in appear_map.items(): - used_type_var_names.add(var_name) + used_type_var_names = appear_map.keys() all_type_vars = get_type_vars(typ) new_variables = [] diff --git a/returns/contrib/mypy/_typeops/visitor.py b/returns/contrib/mypy/_typeops/visitor.py index 6b08d521e..28961d35a 100644 --- a/returns/contrib/mypy/_typeops/visitor.py +++ b/returns/contrib/mypy/_typeops/visitor.py @@ -13,9 +13,6 @@ PartialType, ProperType, TupleType, -) -from mypy.types import Type as MypyType -from mypy.types import ( TypedDictType, TypeOfAny, TypeType, @@ -25,6 +22,7 @@ UnionType, get_proper_type, ) +from mypy.types import Type as MypyType from returns.contrib.mypy._consts import TYPED_KINDN @@ -41,7 +39,7 @@ ) -def translate_kind_instance(typ: MypyType) -> ProperType: # noqa: WPS, C901 +def translate_kind_instance(typ: MypyType) -> ProperType: # noqa: C901, WPS210, WPS212, WPS231 """ We use this ugly hack to translate ``KindN[x, y]`` into ``x[y]``. @@ -55,7 +53,7 @@ def translate_kind_instance(typ: MypyType) -> ProperType: # noqa: WPS, C901 if isinstance(typ, _LEAF_TYPES): # noqa: WPS223 return typ - elif isinstance(typ, Instance): + if isinstance(typ, Instance): last_known_value: LiteralType | None = None if typ.last_known_value is not None: raw_last_known_value = translate_kind_instance(typ.last_known_value) @@ -72,19 +70,19 @@ def translate_kind_instance(typ: MypyType) -> ProperType: # noqa: WPS, C901 return _process_kinded_type(instance) return instance - elif isinstance(typ, CallableType): + if isinstance(typ, CallableType): return typ.copy_modified( arg_types=_translate_types(typ.arg_types), ret_type=translate_kind_instance(typ.ret_type), ) - elif isinstance(typ, TupleType): + if isinstance(typ, TupleType): return TupleType( _translate_types(typ.items), translate_kind_instance(typ.partial_fallback), # type: ignore typ.line, typ.column, ) - elif isinstance(typ, TypedDictType): + if isinstance(typ, TypedDictType): dict_items: dict[str, MypyType] = { item_name: translate_kind_instance(item_type) for item_name, item_type in typ.items.items() @@ -97,7 +95,7 @@ def translate_kind_instance(typ: MypyType) -> ProperType: # noqa: WPS, C901 line=typ.line, column=typ.column, ) - elif isinstance(typ, LiteralType): + if isinstance(typ, LiteralType): fallback = translate_kind_instance(typ.fallback) assert isinstance(fallback, Instance) return LiteralType( @@ -106,16 +104,16 @@ def translate_kind_instance(typ: MypyType) -> ProperType: # noqa: WPS, C901 line=typ.line, column=typ.column, ) - elif isinstance(typ, UnionType): + if isinstance(typ, UnionType): return UnionType(_translate_types(typ.items), typ.line, typ.column) - elif isinstance(typ, Overloaded): + if isinstance(typ, Overloaded): functions: list[CallableType] = [] for func in typ.items: new = translate_kind_instance(func) assert isinstance(new, CallableType) functions.append(new) return Overloaded(items=functions) - elif isinstance(typ, TypeType): + if isinstance(typ, TypeType): return TypeType.make_normalized( translate_kind_instance(typ.item), line=typ.line, @@ -136,9 +134,9 @@ def _process_kinded_type(kind: Instance) -> ProperType: real_type = get_proper_type(kind.args[0]) if isinstance(real_type, TypeVarType): return get_proper_type(erase_to_bound(real_type)) - elif isinstance(real_type, Instance): + if isinstance(real_type, Instance): return real_type.copy_modified( - args=kind.args[1:len(real_type.args) + 1], + args=kind.args[1 : len(real_type.args) + 1], ) # This should never happen, probably can be an exception: diff --git a/returns/contrib/mypy/returns_plugin.py b/returns/contrib/mypy/returns_plugin.py index 8e77d6438..e50df9a3e 100644 --- a/returns/contrib/mypy/returns_plugin.py +++ b/returns/contrib/mypy/returns_plugin.py @@ -10,8 +10,9 @@ We use ``pytest-mypy-plugins`` to test that it works correctly, see: https://github.com/mkurnikov/pytest-mypy-plugins """ + from collections.abc import Callable, Mapping -from typing import ClassVar, Optional, final +from typing import ClassVar, final from mypy.nodes import SymbolTableNode from mypy.plugin import ( @@ -42,7 +43,7 @@ #: Type for a function hook that need a definition node. _FunctionDefCallback = Callable[ - [Optional[SymbolTableNode]], + [SymbolTableNode | None], Callable[[FunctionContext], MypyType], ] @@ -59,6 +60,7 @@ # Interface # ========= + @final class _ReturnsPlugin(Plugin): """Our main plugin to dispatch different callbacks to specific features.""" diff --git a/returns/contrib/pytest/plugin.py b/returns/contrib/pytest/plugin.py index 601946960..046c96aa5 100644 --- a/returns/contrib/pytest/plugin.py +++ b/returns/contrib/pytest/plugin.py @@ -4,7 +4,7 @@ from contextlib import ExitStack, contextmanager from functools import partial, wraps from types import FrameType, MappingProxyType -from typing import TYPE_CHECKING, Any, Final, TypeVar, Union, final +from typing import TYPE_CHECKING, Any, Final, TypeAlias, TypeVar, Union, final from unittest import mock import pytest @@ -21,7 +21,7 @@ # Also, the object itself cannot be (in) the key because # (1) we cannot always assume hashability and # (2) we need to track the object identity, not its value -_ErrorsHandled = dict[int, Any] +_ErrorsHandled: TypeAlias = dict[int, Any] _FunctionType = TypeVar('_FunctionType', bound=Callable) _ReturnsResultType = TypeVar( @@ -34,7 +34,7 @@ class ReturnsAsserts: """Class with helpers assertions to check containers.""" - __slots__ = ('_errors_handled', ) + __slots__ = ('_errors_handled',) def __init__(self, errors_handled: _ErrorsHandled) -> None: """Constructor for this type.""" @@ -49,7 +49,8 @@ def assert_equal( # noqa: WPS602 backend: str = 'asyncio', ) -> None: """Can compare two containers even with extra calling and awaiting.""" - from returns.primitives.asserts import assert_equal + from returns.primitives.asserts import assert_equal # noqa: PLC0415 + assert_equal(first, second, deps=deps, backend=backend) def is_error_handled(self, container) -> bool: @@ -76,9 +77,7 @@ def assert_trace( # noqa: WPS602 pass # noqa: WPS420 else: pytest.fail( - 'No container {0} was created'.format( - trace_type.__class__.__name__, - ), + f'No container {type(trace_type).__name__} was created', ) finally: sys.settrace(old_tracer) @@ -91,24 +90,21 @@ def _trace_function( event: str, arg: Any, ) -> None: - is_desired_type_call = ( - event == 'call' and - ( - # Some containers is created through functions and others - # is created directly using class constructors! - # The first line covers when it's created through a function - # The second line covers when it's created through a - # class constructor - frame.f_code is getattr(trace_type, '__code__', None) or - frame.f_code is getattr(trace_type.__init__, '__code__', None) # type: ignore[misc] # noqa: E501 - ) + is_desired_type_call = event == 'call' and ( + # Some containers is created through functions and others + # is created directly using class constructors! + # The first line covers when it's created through a function + # The second line covers when it's created through a + # class constructor + frame.f_code is getattr(trace_type, '__code__', None) + or frame.f_code is getattr(trace_type.__init__, '__code__', None) # type: ignore[misc] ) if is_desired_type_call: current_call_stack = inspect.stack() function_to_search_code = getattr(function_to_search, '__code__', None) for frame_info in current_call_stack: if function_to_search_code is frame_info.frame.f_code: - raise _DesiredFunctionFound() + raise _DesiredFunctionFound class _DesiredFunctionFound(BaseException): # noqa: WPS418 @@ -124,9 +120,9 @@ def pytest_configure(config) -> None: config.addinivalue_line( 'markers', ( - 'returns_lawful: all tests under `check_all_laws` ' + - 'is marked this way, ' + - 'use `-m "not returns_lawful"` to skip them.' + 'returns_lawful: all tests under `check_all_laws` ' + + 'is marked this way, ' + + 'use `-m "not returns_lawful"` to skip them.' ), ) @@ -145,24 +141,26 @@ def _spy_error_handling() -> Iterator[_ErrorsHandled]: with ExitStack() as cleanup: for container in _containers_to_patch(): for method, patch in _ERROR_HANDLING_PATCHERS.items(): - cleanup.enter_context(mock.patch.object( - container, - method, - patch(getattr(container, method), errs=errs), - )) + cleanup.enter_context( + mock.patch.object( + container, + method, + patch(getattr(container, method), errs=errs), + ) + ) yield errs # delayed imports are needed to prevent messing up coverage def _containers_to_patch() -> list: - from returns.context import ( + from returns.context import ( # noqa: PLC0415 RequiresContextFutureResult, RequiresContextIOResult, RequiresContextResult, ) - from returns.future import FutureResult - from returns.io import IOFailure, IOSuccess - from returns.result import Failure, Success + from returns.future import FutureResult # noqa: PLC0415 + from returns.io import IOFailure, IOSuccess # noqa: PLC0415 + from returns.result import Failure, Success # noqa: PLC0415 return [ Success, @@ -177,36 +175,46 @@ def _containers_to_patch() -> list: def _patched_error_handler( - original: _FunctionType, errs: _ErrorsHandled, + original: _FunctionType, + errs: _ErrorsHandled, ) -> _FunctionType: if inspect.iscoroutinefunction(original): + async def wrapper(self, *args, **kwargs): original_result = await original(self, *args, **kwargs) errs[id(original_result)] = original_result return original_result + else: + def wrapper(self, *args, **kwargs): original_result = original(self, *args, **kwargs) errs[id(original_result)] = original_result return original_result + return wraps(original)(wrapper) # type: ignore def _patched_error_copier( - original: _FunctionType, errs: _ErrorsHandled, + original: _FunctionType, + errs: _ErrorsHandled, ) -> _FunctionType: if inspect.iscoroutinefunction(original): + async def wrapper(self, *args, **kwargs): original_result = await original(self, *args, **kwargs) if id(self) in errs: errs[id(original_result)] = original_result return original_result + else: + def wrapper(self, *args, **kwargs): original_result = original(self, *args, **kwargs) if id(self) in errs: errs[id(original_result)] = original_result return original_result + return wraps(original)(wrapper) # type: ignore diff --git a/returns/converters.py b/returns/converters.py index ee0bd673c..6cedbd9af 100644 --- a/returns/converters.py +++ b/returns/converters.py @@ -74,16 +74,14 @@ def result_to_maybe( @overload def maybe_to_result( maybe_container: Maybe[_FirstType], -) -> Result[_FirstType, None]: - """No default case.""" +) -> Result[_FirstType, None]: ... @overload def maybe_to_result( maybe_container: Maybe[_FirstType], default_error: _SecondType, -) -> Result[_FirstType, _SecondType]: - """Default value case.""" +) -> Result[_FirstType, _SecondType]: ... def maybe_to_result( diff --git a/returns/curry.py b/returns/curry.py index 21d9041ad..0aec48d8b 100644 --- a/returns/curry.py +++ b/returns/curry.py @@ -2,15 +2,15 @@ from functools import partial as _partial from functools import wraps from inspect import BoundArguments, Signature -from typing import Any, TypeVar, Union +from typing import Any, TypeAlias, TypeVar -_FirstType = TypeVar('_FirstType') -_SecondType = TypeVar('_SecondType') _ReturnType = TypeVar('_ReturnType') def partial( - func: Callable[..., _ReturnType], *args: Any, **kwargs: Any, + func: Callable[..., _ReturnType], + *args: Any, + **kwargs: Any, ) -> Callable[..., _ReturnType]: """ Typed partial application. @@ -120,6 +120,7 @@ def curry(function: Callable[..., _ReturnType]) -> Callable[..., _ReturnType]: def decorator(*args, **kwargs): return _eager_curry(function, argspec, args, kwargs) + return wraps(function)(decorator) @@ -143,15 +144,17 @@ def _eager_curry( # the function args and args of the curry implementation. def decorator(*inner_args, **inner_kwargs): return _eager_curry(function, intermediate, inner_args, inner_kwargs) + return wraps(function)(decorator) -_ArgSpec = Union[ +_ArgSpec: TypeAlias = ( # Case when all arguments are bound and function can be called: - tuple[None, tuple[tuple, dict]], + tuple[None, tuple[tuple, dict]] + | # Case when there are still unbound arguments: - tuple[BoundArguments, None], -] + tuple[BoundArguments, None] +) def _intermediate_argspec( diff --git a/returns/functions.py b/returns/functions.py index bf3f9b3ee..9419b1e3b 100644 --- a/returns/functions.py +++ b/returns/functions.py @@ -70,9 +70,11 @@ def tap( - https://github.com/dry-python/returns/issues/145 """ + def decorator(argument_to_return: _FirstType) -> _FirstType: function(argument_to_return) return argument_to_return + return decorator @@ -101,8 +103,10 @@ def untap( - https://github.com/dry-python/returns/issues/145 """ + def decorator(argument_to_return: _FirstType) -> None: function(argument_to_return) + return decorator @@ -147,10 +151,12 @@ def not_(function: Callable[_FuncParams, bool]) -> Callable[_FuncParams, bool]: >>> assert not_(is_successful)(Failure(1)) is True """ + @wraps(function) def decorator( *args: _FuncParams.args, **kwargs: _FuncParams.kwargs, ) -> bool: return not function(*args, **kwargs) + return decorator diff --git a/returns/future.py b/returns/future.py index 9195fef6d..ecee5cf4d 100644 --- a/returns/future.py +++ b/returns/future.py @@ -28,9 +28,9 @@ from returns.result import Failure, Result, Success # Definitions: -_ValueType = TypeVar('_ValueType', covariant=True) +_ValueType_co = TypeVar('_ValueType_co', covariant=True) _NewValueType = TypeVar('_NewValueType') -_ErrorType = TypeVar('_ErrorType', covariant=True) +_ErrorType_co = TypeVar('_ErrorType_co', covariant=True) _NewErrorType = TypeVar('_NewErrorType') _FuncParams = ParamSpec('_FuncParams') @@ -42,7 +42,8 @@ # Public composition helpers: -async def async_identity(instance: _FirstType) -> _FirstType: + +async def async_identity(instance: _FirstType) -> _FirstType: # noqa: RUF029 """ Async function that returns its argument. @@ -62,11 +63,12 @@ async def async_identity(instance: _FirstType) -> _FirstType: # Future # ====== + @final class Future( # type: ignore[type-var] BaseContainer, - SupportsKind1['Future', _ValueType], - FutureBased1[_ValueType], + SupportsKind1['Future', _ValueType_co], + FutureBased1[_ValueType_co], ): """ Container to easily compose ``async`` functions. @@ -98,9 +100,9 @@ class Future( # type: ignore[type-var] __slots__ = () - _inner_value: Awaitable[_ValueType] + _inner_value: Awaitable[_ValueType_co] - def __init__(self, inner_value: Awaitable[_ValueType]) -> None: + def __init__(self, inner_value: Awaitable[_ValueType_co]) -> None: """ Public constructor for this type. Also required for typing. @@ -119,7 +121,7 @@ def __init__(self, inner_value: Awaitable[_ValueType]) -> None: """ super().__init__(ReAwaitable(inner_value)) - def __await__(self) -> Generator[None, None, IO[_ValueType]]: + def __await__(self) -> Generator[None, None, IO[_ValueType_co]]: """ By defining this magic method we make ``Future`` awaitable. @@ -145,9 +147,9 @@ def __await__(self) -> Generator[None, None, IO[_ValueType]]: - https://bit.ly/2SfayNc """ - return self.awaitable().__await__() # noqa: WPS609 + return self.awaitable().__await__() - async def awaitable(self) -> IO[_ValueType]: + async def awaitable(self) -> IO[_ValueType_co]: """ Transforms ``Future[a]`` to ``Awaitable[IO[a]]``. @@ -169,7 +171,7 @@ async def awaitable(self) -> IO[_ValueType]: def map( self, - function: Callable[[_ValueType], _NewValueType], + function: Callable[[_ValueType_co], _NewValueType], ) -> 'Future[_NewValueType]': """ Applies function to the inner value. @@ -197,7 +199,7 @@ def map( def apply( self, - container: Kind1['Future', Callable[[_ValueType], _NewValueType]], + container: Kind1['Future', Callable[[_ValueType_co], _NewValueType]], ) -> 'Future[_NewValueType]': """ Calls a wrapped function in a container on this container. @@ -221,7 +223,7 @@ def apply( def bind( self, - function: Callable[[_ValueType], Kind1['Future', _NewValueType]], + function: Callable[[_ValueType_co], Kind1['Future', _NewValueType]], ) -> 'Future[_NewValueType]': """ Applies 'function' to the result of a previous calculation. @@ -251,7 +253,7 @@ def bind( def bind_async( self, function: Callable[ - [_ValueType], + [_ValueType_co], Awaitable[Kind1['Future', _NewValueType]], ], ) -> 'Future[_NewValueType]': @@ -283,7 +285,7 @@ def bind_async( def bind_awaitable( self, - function: Callable[[_ValueType], 'Awaitable[_NewValueType]'], + function: Callable[[_ValueType_co], 'Awaitable[_NewValueType]'], ) -> 'Future[_NewValueType]': """ Allows to compose a container and a regular ``async`` function. @@ -306,13 +308,16 @@ def bind_awaitable( ... ) == IO(2) """ - return Future(_future.async_bind_awaitable( - function, self._inner_value, - )) + return Future( + _future.async_bind_awaitable( + function, + self._inner_value, + ) + ) def bind_io( self, - function: Callable[[_ValueType], IO[_NewValueType]], + function: Callable[[_ValueType_co], IO[_NewValueType]], ) -> 'Future[_NewValueType]': """ Applies 'function' to the result of a previous calculation. @@ -336,10 +341,12 @@ def bind_io( """ return Future(_future.async_bind_io(function, self._inner_value)) - def __aiter__(self) -> AsyncIterator[_ValueType]: # noqa: WPS611 + def __aiter__(self) -> AsyncIterator[_ValueType_co]: # noqa: WPS611 """API for :ref:`do-notation`.""" - async def factory() -> AsyncGenerator[_ValueType, None]: + + async def factory() -> AsyncGenerator[_ValueType_co, None]: yield await self._inner_value + return factory() @classmethod @@ -368,8 +375,10 @@ def do( See :ref:`do-notation` to learn more. """ + async def factory() -> _NewValueType: - return await expr.__anext__() # noqa: WPS609 + return await anext(expr) + return Future(factory()) @classmethod @@ -396,7 +405,8 @@ def from_value(cls, inner_value: _NewValueType) -> 'Future[_NewValueType]': @classmethod def from_future( - cls, inner_value: 'Future[_NewValueType]', + cls, + inner_value: 'Future[_NewValueType]', ) -> 'Future[_NewValueType]': """ Creates a new ``Future`` from the existing one. @@ -431,7 +441,7 @@ def from_io(cls, inner_value: IO[_NewValueType]) -> 'Future[_NewValueType]': >>> assert anyio.run(main) is True """ - return Future(async_identity(inner_value._inner_value)) + return Future(async_identity(inner_value._inner_value)) # noqa: SLF001 @classmethod def from_future_result( @@ -454,17 +464,18 @@ def from_future_result( >>> assert anyio.run(container.awaitable) == IO(Success(1)) """ - return Future(inner_value._inner_value) + return Future(inner_value._inner_value) # noqa: SLF001 # Decorators: + def future( function: Callable[ _FuncParams, - Coroutine[_FirstType, _SecondType, _ValueType], + Coroutine[_FirstType, _SecondType, _ValueType_co], ], -) -> Callable[_FuncParams, Future[_ValueType]]: +) -> Callable[_FuncParams, Future[_ValueType_co]]: """ Decorator to turn a coroutine definition into ``Future`` container. @@ -481,18 +492,20 @@ def future( >>> assert anyio.run(test(1).awaitable) == IO(2) """ + @wraps(function) def decorator( *args: _FuncParams.args, **kwargs: _FuncParams.kwargs, - ) -> Future[_ValueType]: + ) -> Future[_ValueType_co]: return Future(function(*args, **kwargs)) + return decorator def asyncify( - function: Callable[_FuncParams, _ValueType], -) -> Callable[_FuncParams, Coroutine[Any, Any, _ValueType]]: + function: Callable[_FuncParams, _ValueType_co], +) -> Callable[_FuncParams, Coroutine[Any, Any, _ValueType_co]]: """ Decorator to turn a common function into an asynchronous function. @@ -524,23 +537,26 @@ def asyncify( https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/ """ + @wraps(function) - async def decorator( + async def decorator( # noqa: RUF029 *args: _FuncParams.args, **kwargs: _FuncParams.kwargs, - ) -> _ValueType: + ) -> _ValueType_co: return function(*args, **kwargs) + return decorator # FutureResult # ============ + @final class FutureResult( # type: ignore[type-var] BaseContainer, - SupportsKind2['FutureResult', _ValueType, _ErrorType], - FutureResultBased2[_ValueType, _ErrorType], + SupportsKind2['FutureResult', _ValueType_co, _ErrorType_co], + FutureResultBased2[_ValueType_co, _ErrorType_co], ): """ Container to easily compose ``async`` functions. @@ -574,11 +590,11 @@ class FutureResult( # type: ignore[type-var] __slots__ = () - _inner_value: Awaitable[Result[_ValueType, _ErrorType]] + _inner_value: Awaitable[Result[_ValueType_co, _ErrorType_co]] def __init__( self, - inner_value: Awaitable[Result[_ValueType, _ErrorType]], + inner_value: Awaitable[Result[_ValueType_co, _ErrorType_co]], ) -> None: """ Public constructor for this type. Also required for typing. @@ -599,8 +615,12 @@ def __init__( """ super().__init__(ReAwaitable(inner_value)) - def __await__(self) -> Generator[ - None, None, IOResult[_ValueType, _ErrorType], + def __await__( + self, + ) -> Generator[ + None, + None, + IOResult[_ValueType_co, _ErrorType_co], ]: """ By defining this magic method we make ``FutureResult`` awaitable. @@ -627,9 +647,9 @@ def __await__(self) -> Generator[ - https://bit.ly/2SfayNc """ - return self.awaitable().__await__() # noqa: WPS609 + return self.awaitable().__await__() - async def awaitable(self) -> IOResult[_ValueType, _ErrorType]: + async def awaitable(self) -> IOResult[_ValueType_co, _ErrorType_co]: """ Transforms ``FutureResult[a, b]`` to ``Awaitable[IOResult[a, b]]``. @@ -651,7 +671,7 @@ async def awaitable(self) -> IOResult[_ValueType, _ErrorType]: """ return IOResult.from_result(await self._inner_value) - def swap(self) -> 'FutureResult[_ErrorType, _ValueType]': + def swap(self) -> 'FutureResult[_ErrorType_co, _ValueType_co]': """ Swaps value and error types. @@ -675,8 +695,8 @@ def swap(self) -> 'FutureResult[_ErrorType, _ValueType]': def map( self, - function: Callable[[_ValueType], _NewValueType], - ) -> 'FutureResult[_NewValueType, _ErrorType]': + function: Callable[[_ValueType_co], _NewValueType], + ) -> 'FutureResult[_NewValueType, _ErrorType_co]': """ Applies function to the inner value. @@ -702,18 +722,21 @@ def map( ... ) == IOFailure(1) """ - return FutureResult(_future_result.async_map( - function, self._inner_value, - )) + return FutureResult( + _future_result.async_map( + function, + self._inner_value, + ) + ) def apply( self, container: Kind2[ 'FutureResult', - Callable[[_ValueType], _NewValueType], - _ErrorType, + Callable[[_ValueType_co], _NewValueType], + _ErrorType_co, ], - ) -> 'FutureResult[_NewValueType, _ErrorType]': + ) -> 'FutureResult[_NewValueType, _ErrorType_co]': """ Calls a wrapped function in a container on this container. @@ -749,17 +772,20 @@ def apply( ... ) == IOFailure(1) """ - return FutureResult(_future_result.async_apply( - dekind(container), self._inner_value, - )) + return FutureResult( + _future_result.async_apply( + dekind(container), + self._inner_value, + ) + ) def bind( self, function: Callable[ - [_ValueType], - Kind2['FutureResult', _NewValueType, _ErrorType], + [_ValueType_co], + Kind2['FutureResult', _NewValueType, _ErrorType_co], ], - ) -> 'FutureResult[_NewValueType, _ErrorType]': + ) -> 'FutureResult[_NewValueType, _ErrorType_co]': """ Applies 'function' to the result of a previous calculation. @@ -783,9 +809,12 @@ def bind( ... ) == IOFailure(1) """ - return FutureResult(_future_result.async_bind( - function, self._inner_value, - )) + return FutureResult( + _future_result.async_bind( + function, + self._inner_value, + ) + ) #: Alias for `bind` method. #: Part of the `FutureResultBasedN` interface. @@ -794,10 +823,10 @@ def bind( def bind_async( self, function: Callable[ - [_ValueType], - Awaitable[Kind2['FutureResult', _NewValueType, _ErrorType]], + [_ValueType_co], + Awaitable[Kind2['FutureResult', _NewValueType, _ErrorType_co]], ], - ) -> 'FutureResult[_NewValueType, _ErrorType]': + ) -> 'FutureResult[_NewValueType, _ErrorType_co]': """ Composes a container and ``async`` function returning container. @@ -822,9 +851,12 @@ def bind_async( ... ) == IOFailure(1) """ - return FutureResult(_future_result.async_bind_async( - function, self._inner_value, - )) + return FutureResult( + _future_result.async_bind_async( + function, + self._inner_value, + ) + ) #: Alias for `bind_async` method. #: Part of the `FutureResultBasedN` interface. @@ -832,8 +864,8 @@ def bind_async( def bind_awaitable( self, - function: Callable[[_ValueType], Awaitable[_NewValueType]], - ) -> 'FutureResult[_NewValueType, _ErrorType]': + function: Callable[[_ValueType_co], Awaitable[_NewValueType]], + ) -> 'FutureResult[_NewValueType, _ErrorType_co]': """ Allows to compose a container and a regular ``async`` function. @@ -858,14 +890,19 @@ def bind_awaitable( ... ) == IOFailure(1) """ - return FutureResult(_future_result.async_bind_awaitable( - function, self._inner_value, - )) + return FutureResult( + _future_result.async_bind_awaitable( + function, + self._inner_value, + ) + ) def bind_result( self, - function: Callable[[_ValueType], Result[_NewValueType, _ErrorType]], - ) -> 'FutureResult[_NewValueType, _ErrorType]': + function: Callable[ + [_ValueType_co], Result[_NewValueType, _ErrorType_co] + ], + ) -> 'FutureResult[_NewValueType, _ErrorType_co]': """ Binds a function returning ``Result[a, b]`` container. @@ -887,14 +924,19 @@ def bind_result( ... ) == IOFailure('a') """ - return FutureResult(_future_result.async_bind_result( - function, self._inner_value, - )) + return FutureResult( + _future_result.async_bind_result( + function, + self._inner_value, + ) + ) def bind_ioresult( self, - function: Callable[[_ValueType], IOResult[_NewValueType, _ErrorType]], - ) -> 'FutureResult[_NewValueType, _ErrorType]': + function: Callable[ + [_ValueType_co], IOResult[_NewValueType, _ErrorType_co] + ], + ) -> 'FutureResult[_NewValueType, _ErrorType_co]': """ Binds a function returning ``IOResult[a, b]`` container. @@ -915,14 +957,17 @@ def bind_ioresult( ... ) == IOFailure('a') """ - return FutureResult(_future_result.async_bind_ioresult( - function, self._inner_value, - )) + return FutureResult( + _future_result.async_bind_ioresult( + function, + self._inner_value, + ) + ) def bind_io( self, - function: Callable[[_ValueType], IO[_NewValueType]], - ) -> 'FutureResult[_NewValueType, _ErrorType]': + function: Callable[[_ValueType_co], IO[_NewValueType]], + ) -> 'FutureResult[_NewValueType, _ErrorType_co]': """ Binds a function returning ``IO[a]`` container. @@ -943,14 +988,17 @@ def bind_io( ... ) == IOFailure(1) """ - return FutureResult(_future_result.async_bind_io( - function, self._inner_value, - )) + return FutureResult( + _future_result.async_bind_io( + function, + self._inner_value, + ) + ) def bind_future( self, - function: Callable[[_ValueType], Future[_NewValueType]], - ) -> 'FutureResult[_NewValueType, _ErrorType]': + function: Callable[[_ValueType_co], Future[_NewValueType]], + ) -> 'FutureResult[_NewValueType, _ErrorType_co]': """ Binds a function returning ``Future[a]`` container. @@ -971,14 +1019,17 @@ def bind_future( ... ) == IOFailure(1) """ - return FutureResult(_future_result.async_bind_future( - function, self._inner_value, - )) + return FutureResult( + _future_result.async_bind_future( + function, + self._inner_value, + ) + ) def bind_async_future( self, - function: Callable[[_ValueType], Awaitable['Future[_NewValueType]']], - ) -> 'FutureResult[_NewValueType, _ErrorType]': + function: Callable[[_ValueType_co], Awaitable['Future[_NewValueType]']], + ) -> 'FutureResult[_NewValueType, _ErrorType_co]': """ Composes a container and ``async`` function returning ``Future``. @@ -1004,14 +1055,17 @@ def bind_async_future( ... ) == IOFailure(1) """ - return FutureResult(_future_result.async_bind_async_future( - function, self._inner_value, - )) + return FutureResult( + _future_result.async_bind_async_future( + function, + self._inner_value, + ) + ) def alt( self, - function: Callable[[_ErrorType], _NewErrorType], - ) -> 'FutureResult[_ValueType, _NewErrorType]': + function: Callable[[_ErrorType_co], _NewErrorType], + ) -> 'FutureResult[_ValueType_co, _NewErrorType]': """ Composes failed container with a pure function to modify failure. @@ -1032,17 +1086,20 @@ def alt( ... ) == IOFailure(2) """ - return FutureResult(_future_result.async_alt( - function, self._inner_value, - )) + return FutureResult( + _future_result.async_alt( + function, + self._inner_value, + ) + ) def lash( self, function: Callable[ - [_ErrorType], - Kind2['FutureResult', _ValueType, _NewErrorType], + [_ErrorType_co], + Kind2['FutureResult', _ValueType_co, _NewErrorType], ], - ) -> 'FutureResult[_ValueType, _NewErrorType]': + ) -> 'FutureResult[_ValueType_co, _NewErrorType]': """ Composes failed container with a function that returns a container. @@ -1063,17 +1120,20 @@ def lash( ... ) == IOSuccess(2) """ - return FutureResult(_future_result.async_lash( - function, self._inner_value, - )) + return FutureResult( + _future_result.async_lash( + function, + self._inner_value, + ) + ) def compose_result( self, function: Callable[ - [Result[_ValueType, _ErrorType]], - Kind2['FutureResult', _NewValueType, _ErrorType], + [Result[_ValueType_co, _ErrorType_co]], + Kind2['FutureResult', _NewValueType, _ErrorType_co], ], - ) -> 'FutureResult[_NewValueType, _ErrorType]': + ) -> 'FutureResult[_NewValueType, _ErrorType_co]': """ Composes inner ``Result`` with ``FutureResult`` returning function. @@ -1099,16 +1159,20 @@ def compose_result( ... ) == IOFailure(1) """ - return FutureResult(_future_result.async_compose_result( - function, - self._inner_value, - )) + return FutureResult( + _future_result.async_compose_result( + function, + self._inner_value, + ) + ) - def __aiter__(self) -> AsyncIterator[_ValueType]: # noqa: WPS611 + def __aiter__(self) -> AsyncIterator[_ValueType_co]: # noqa: WPS611 """API for :ref:`do-notation`.""" - async def factory() -> AsyncGenerator[_ValueType, None]: - for inner_value in (await self._inner_value): + + async def factory() -> AsyncGenerator[_ValueType_co, None]: + for inner_value in await self._inner_value: yield inner_value # will only yield once + return factory() @classmethod @@ -1146,11 +1210,13 @@ def do( See :ref:`do-notation` to learn more. """ + async def factory() -> Result[_NewValueType, _NewErrorType]: try: - return Success(await expr.__anext__()) # noqa: WPS609 + return Success(await anext(expr)) except UnwrapFailedError as exc: return exc.halted_container # type: ignore + return FutureResult(factory()) @classmethod @@ -1179,7 +1245,7 @@ def from_typecast( >>> anyio.run(main) """ - return FutureResult(inner_value._inner_value) + return FutureResult(inner_value._inner_value) # noqa: SLF001 @classmethod def from_future( @@ -1276,7 +1342,7 @@ def from_io( >>> anyio.run(main) """ - return FutureResult.from_value(inner_value._inner_value) + return FutureResult.from_value(inner_value._inner_value) # noqa: SLF001 @classmethod def from_failed_io( @@ -1300,7 +1366,7 @@ def from_failed_io( >>> anyio.run(main) """ - return FutureResult.from_failure(inner_value._inner_value) + return FutureResult.from_failure(inner_value._inner_value) # noqa: SLF001 @classmethod def from_ioresult( @@ -1327,7 +1393,7 @@ def from_ioresult( >>> anyio.run(main) """ - return FutureResult(async_identity(inner_value._inner_value)) + return FutureResult(async_identity(inner_value._inner_value)) # noqa: SLF001 @classmethod def from_result( @@ -1448,8 +1514,8 @@ def FutureFailure( # noqa: N802 return FutureResult.from_failure(inner_value) -#: Alias for ``FutureResult[_ValueType, Exception]``. -FutureResultE: TypeAlias = FutureResult[_ValueType, Exception] +#: Alias for ``FutureResult[_ValueType_co, Exception]``. +FutureResultE: TypeAlias = FutureResult[_ValueType_co, Exception] _ExceptionType = TypeVar('_ExceptionType', bound=Exception) @@ -1457,15 +1523,15 @@ def FutureFailure( # noqa: N802 # Decorators: + @overload def future_safe( exceptions: Callable[ _FuncParams, - Coroutine[_FirstType, _SecondType, _ValueType], + Coroutine[_FirstType, _SecondType, _ValueType_co], ], /, -) -> Callable[_FuncParams, FutureResultE[_ValueType]]: - """Decorator to convert exception-throwing for any kind of Exception.""" +) -> Callable[_FuncParams, FutureResultE[_ValueType_co]]: ... @overload @@ -1475,32 +1541,31 @@ def future_safe( [ Callable[ _FuncParams, - Coroutine[_FirstType, _SecondType, _ValueType], + Coroutine[_FirstType, _SecondType, _ValueType_co], ], ], - Callable[_FuncParams, FutureResult[_ValueType, _ExceptionType]], -]: - """Decorator to convert exception-throwing just for a set of Exceptions.""" + Callable[_FuncParams, FutureResult[_ValueType_co, _ExceptionType]], +]: ... -def future_safe( # noqa: C901, WPS212, WPS234, +def future_safe( # noqa: WPS212, WPS234, exceptions: ( Callable[ _FuncParams, - Coroutine[_FirstType, _SecondType, _ValueType], - ] | - tuple[type[_ExceptionType], ...] + Coroutine[_FirstType, _SecondType, _ValueType_co], + ] + | tuple[type[_ExceptionType], ...] ), ) -> ( - Callable[_FuncParams, FutureResultE[_ValueType]] | - Callable[ + Callable[_FuncParams, FutureResultE[_ValueType_co]] + | Callable[ [ Callable[ _FuncParams, - Coroutine[_FirstType, _SecondType, _ValueType], + Coroutine[_FirstType, _SecondType, _ValueType_co], ], ], - Callable[_FuncParams, FutureResult[_ValueType, _ExceptionType]], + Callable[_FuncParams, FutureResult[_ValueType_co, _ExceptionType]], ] ): """ @@ -1554,17 +1619,18 @@ def future_safe( # noqa: C901, WPS212, WPS234, decorators, but works with ``async`` functions. """ + def _future_safe_factory( # noqa: WPS430 function: Callable[ _FuncParams, - Coroutine[_FirstType, _SecondType, _ValueType], + Coroutine[_FirstType, _SecondType, _ValueType_co], ], inner_exceptions: tuple[type[_ExceptionType], ...], - ) -> Callable[_FuncParams, FutureResult[_ValueType, _ExceptionType]]: + ) -> Callable[_FuncParams, FutureResult[_ValueType_co, _ExceptionType]]: async def factory( *args: _FuncParams.args, **kwargs: _FuncParams.kwargs, - ) -> Result[_ValueType, _ExceptionType]: + ) -> Result[_ValueType_co, _ExceptionType]: try: return Success(await function(*args, **kwargs)) except inner_exceptions as exc: @@ -1574,9 +1640,11 @@ async def factory( def decorator( *args: _FuncParams.args, **kwargs: _FuncParams.kwargs, - ) -> FutureResult[_ValueType, _ExceptionType]: + ) -> FutureResult[_ValueType_co, _ExceptionType]: return FutureResult(factory(*args, **kwargs)) + return decorator + if isinstance(exceptions, tuple): return lambda function: _future_safe_factory(function, exceptions) return _future_safe_factory( diff --git a/returns/interfaces/altable.py b/returns/interfaces/altable.py index cccc34f2f..f0113c10f 100644 --- a/returns/interfaces/altable.py +++ b/returns/interfaces/altable.py @@ -59,8 +59,8 @@ def associative_law( class AltableN( - Generic[_FirstType, _SecondType, _ThirdType], Lawful['AltableN[_FirstType, _SecondType, _ThirdType]'], + Generic[_FirstType, _SecondType, _ThirdType], ): """Modifies the second type argument with a pure function.""" diff --git a/returns/interfaces/applicative.py b/returns/interfaces/applicative.py index a963d55d2..bd8876ddb 100644 --- a/returns/interfaces/applicative.py +++ b/returns/interfaces/applicative.py @@ -158,7 +158,7 @@ def apply( @classmethod @abstractmethod def from_value( - cls: type[_ApplicativeType], # noqa: N805 + cls: type[_ApplicativeType], inner_value: _UpdatedType, ) -> KindN[_ApplicativeType, _UpdatedType, _SecondType, _ThirdType]: """Unit method to create new containers from any raw value.""" diff --git a/returns/interfaces/container.py b/returns/interfaces/container.py index 6709928a6..0972f06df 100644 --- a/returns/interfaces/container.py +++ b/returns/interfaces/container.py @@ -70,7 +70,7 @@ def right_identity_law( assert_equal( container, container.bind( - lambda inner: container.from_value(inner), + container.from_value, ), ) @@ -91,7 +91,7 @@ def associative_law( The final monad law says that when we have a chain of container functions applications with ``bind``, - it shouldn’t matter how they’re nested. + it shouldn't matter how they're nested. """ assert_equal( container.bind(first).bind(second), diff --git a/returns/interfaces/mappable.py b/returns/interfaces/mappable.py index 3853397f1..a8e5656ae 100644 --- a/returns/interfaces/mappable.py +++ b/returns/interfaces/mappable.py @@ -59,8 +59,8 @@ def associative_law( class MappableN( - Generic[_FirstType, _SecondType, _ThirdType], Lawful['MappableN[_FirstType, _SecondType, _ThirdType]'], + Generic[_FirstType, _SecondType, _ThirdType], ): """ Allows to chain wrapped values in containers with regular functions. diff --git a/returns/interfaces/specific/future.py b/returns/interfaces/specific/future.py index b8b88463a..cdbf349c0 100644 --- a/returns/interfaces/specific/future.py +++ b/returns/interfaces/specific/future.py @@ -27,7 +27,6 @@ _FutureLikeType = TypeVar('_FutureLikeType', bound='FutureLikeN') _AsyncFutureType = TypeVar('_AsyncFutureType', bound='AwaitableFutureN') -_FutureBasedType = TypeVar('_FutureBasedType', bound='FutureBasedN') class FutureLikeN(io.IOLikeN[_FirstType, _SecondType, _ThirdType]): @@ -75,7 +74,7 @@ def bind_awaitable( @classmethod @abstractmethod def from_future( - cls: type[_FutureLikeType], # noqa: N805 + cls: type[_FutureLikeType], inner_value: Future[_UpdatedType], ) -> KindN[_FutureLikeType, _UpdatedType, _SecondType, _ThirdType]: """Unit method to create new containers from successful ``Future``.""" @@ -101,8 +100,12 @@ class AwaitableFutureN(Generic[_FirstType, _SecondType, _ThirdType]): __slots__ = () @abstractmethod - def __await__(self: _AsyncFutureType) -> Generator[ - Any, Any, io.IOLikeN[_FirstType, _SecondType, _ThirdType], + def __await__( + self: _AsyncFutureType, + ) -> Generator[ + Any, + Any, + io.IOLikeN[_FirstType, _SecondType, _ThirdType], ]: """Magic method to allow ``await`` expression.""" diff --git a/returns/interfaces/specific/future_result.py b/returns/interfaces/specific/future_result.py index e0f07911b..3a65ccb6d 100644 --- a/returns/interfaces/specific/future_result.py +++ b/returns/interfaces/specific/future_result.py @@ -29,7 +29,8 @@ _ErrorType = TypeVar('_ErrorType') _FutureResultLikeType = TypeVar( - '_FutureResultLikeType', bound='FutureResultLikeN', + '_FutureResultLikeType', + bound='FutureResultLikeN', ) @@ -69,14 +70,14 @@ def bind_async_future_result( @classmethod @abstractmethod def from_failed_future( - cls: type[_FutureResultLikeType], # noqa: N805 + cls: type[_FutureResultLikeType], inner_value: Future[_ErrorType], ) -> KindN[_FutureResultLikeType, _FirstType, _ErrorType, _ThirdType]: """Creates new container from a failed ``Future``.""" @classmethod def from_future_result( - cls: type[_FutureResultLikeType], # noqa: N805 + cls: type[_FutureResultLikeType], inner_value: FutureResult[_ValueType, _ErrorType], ) -> KindN[_FutureResultLikeType, _ValueType, _ErrorType, _ThirdType]: """Creates container from ``FutureResult`` instance.""" diff --git a/returns/interfaces/specific/io.py b/returns/interfaces/specific/io.py index 971d9a2a9..a6186db4a 100644 --- a/returns/interfaces/specific/io.py +++ b/returns/interfaces/specific/io.py @@ -42,7 +42,7 @@ def bind_io( @classmethod @abstractmethod def from_io( - cls: type[_IOLikeType], # noqa: N805 + cls: type[_IOLikeType], inner_value: IO[_UpdatedType], ) -> KindN[_IOLikeType, _UpdatedType, _SecondType, _ThirdType]: """Unit method to create new containers from successful ``IO``.""" diff --git a/returns/interfaces/specific/ioresult.py b/returns/interfaces/specific/ioresult.py index b797922d2..9f220095f 100644 --- a/returns/interfaces/specific/ioresult.py +++ b/returns/interfaces/specific/ioresult.py @@ -62,7 +62,7 @@ def compose_result( @classmethod @abstractmethod def from_ioresult( - cls: type[_IOResultLikeType], # noqa: N805 + cls: type[_IOResultLikeType], inner_value: IOResult[_ValueType, _ErrorType], ) -> KindN[_IOResultLikeType, _ValueType, _ErrorType, _ThirdType]: """Unit method to create new containers from ``IOResult`` type.""" @@ -70,7 +70,7 @@ def from_ioresult( @classmethod @abstractmethod def from_failed_io( - cls: type[_IOResultLikeType], # noqa: N805 + cls: type[_IOResultLikeType], inner_value: IO[_ErrorType], ) -> KindN[_IOResultLikeType, _FirstType, _ErrorType, _ThirdType]: """Unit method to create new containers from failed ``IO``.""" diff --git a/returns/interfaces/specific/maybe.py b/returns/interfaces/specific/maybe.py index 5f31f5f1f..b1f7f3352 100644 --- a/returns/interfaces/specific/maybe.py +++ b/returns/interfaces/specific/maybe.py @@ -136,7 +136,7 @@ def bind_optional( @classmethod @abstractmethod def from_optional( - cls: type[_MaybeLikeType], # noqa: N805 + cls: type[_MaybeLikeType], inner_value: _ValueType | None, ) -> KindN[_MaybeLikeType, _ValueType, _SecondType, _ThirdType]: """Unit method to create containers from ``Optional`` value.""" diff --git a/returns/interfaces/specific/reader.py b/returns/interfaces/specific/reader.py index 61de0f2ca..65e2b297a 100644 --- a/returns/interfaces/specific/reader.py +++ b/returns/interfaces/specific/reader.py @@ -49,7 +49,6 @@ _UpdatedType = TypeVar('_UpdatedType') _ValueType = TypeVar('_ValueType') -_ErrorType = TypeVar('_ErrorType') _EnvType = TypeVar('_EnvType') _ReaderLike2Type = TypeVar('_ReaderLike2Type', bound='ReaderLike2') @@ -121,7 +120,7 @@ def ask( @classmethod @abstractmethod def from_context( - cls: type[_ReaderLike2Type], # noqa: N805 + cls: type[_ReaderLike2Type], inner_value: RequiresContext[_ValueType, _EnvType], ) -> Kind2[_ReaderLike2Type, _ValueType, _EnvType]: """Unit method to create new containers from successful ``Reader``.""" @@ -186,7 +185,7 @@ def ask( @classmethod @abstractmethod def from_context( - cls: type[_ReaderLike3Type], # noqa: N805 + cls: type[_ReaderLike3Type], inner_value: RequiresContext[_ValueType, _EnvType], ) -> Kind3[_ReaderLike3Type, _ValueType, _SecondType, _EnvType]: """Unit method to create new containers from successful ``Reader``.""" @@ -233,9 +232,9 @@ def asking_law( env: _SecondType, ) -> None: """Asking for an env, always returns the env.""" - assert container.ask().__call__( # noqa: WPS609 + assert container.ask().__call__( # noqa: PLC2801 env, - ) == container.from_value(env).__call__(env) # noqa: WPS609 + ) == container.from_value(env).__call__(env) # noqa: PLC2801 class ReaderBased2( diff --git a/returns/interfaces/specific/reader_future_result.py b/returns/interfaces/specific/reader_future_result.py index 39b7bd6a3..65b60eb55 100644 --- a/returns/interfaces/specific/reader_future_result.py +++ b/returns/interfaces/specific/reader_future_result.py @@ -81,7 +81,7 @@ def bind_async_context_future_result( @classmethod @abstractmethod def from_future_result_context( - cls: type[_ReaderFutureResultLikeType], # noqa: N805 + cls: type[_ReaderFutureResultLikeType], inner_value: ReaderFutureResult[_ValueType, _ErrorType, _EnvType], ) -> KindN[_ReaderFutureResultLikeType, _ValueType, _ErrorType, _EnvType]: """Unit method to create new containers from ``ReaderFutureResult``.""" @@ -89,7 +89,9 @@ def from_future_result_context( #: Type alias for kinds with three type arguments. ReaderFutureResultLike3 = ReaderFutureResultLikeN[ - _FirstType, _SecondType, _ThirdType, + _FirstType, + _SecondType, + _ThirdType, ] @@ -105,14 +107,15 @@ class _LawSpec(LawSpecDef): @law_definition def asking_law( - container: - ReaderFutureResultBasedN[_FirstType, _SecondType, _ThirdType], + container: ReaderFutureResultBasedN[ + _FirstType, _SecondType, _ThirdType + ], env: _ThirdType, ) -> None: """Asking for an env, always returns the env.""" assert_equal( - container.ask().__call__(env), # noqa: WPS609 - container.from_value(env).__call__(env), # noqa: WPS609 + container.ask().__call__(env), # noqa: PLC2801 + container.from_value(env).__call__(env), # noqa: PLC2801 ) @@ -139,12 +142,12 @@ class ReaderFutureResultBasedN( __slots__ = () - _laws: ClassVar[Sequence[Law]] = ( - Law2(_LawSpec.asking_law), - ) + _laws: ClassVar[Sequence[Law]] = (Law2(_LawSpec.asking_law),) #: Type alias for kinds with three type arguments. ReaderFutureResultBased3 = ReaderFutureResultBasedN[ - _FirstType, _SecondType, _ThirdType, + _FirstType, + _SecondType, + _ThirdType, ] diff --git a/returns/interfaces/specific/reader_ioresult.py b/returns/interfaces/specific/reader_ioresult.py index b4566382e..933092712 100644 --- a/returns/interfaces/specific/reader_ioresult.py +++ b/returns/interfaces/specific/reader_ioresult.py @@ -58,7 +58,7 @@ def bind_context_ioresult( @classmethod @abstractmethod def from_ioresult_context( - cls: type[_ReaderIOResultLikeType], # noqa: N805 + cls: type[_ReaderIOResultLikeType], inner_value: ReaderIOResult[_ValueType, _ErrorType, _EnvType], ) -> KindN[_ReaderIOResultLikeType, _ValueType, _ErrorType, _EnvType]: """Unit method to create new containers from ``ReaderIOResult``.""" @@ -84,9 +84,9 @@ def asking_law( env: _ThirdType, ) -> None: """Asking for an env, always returns the env.""" - assert container.ask().__call__( # noqa: WPS609 + assert container.ask().__call__( # noqa: PLC2801 env, - ) == container.from_value(env).__call__(env) # noqa: WPS609 + ) == container.from_value(env).__call__(env) # noqa: PLC2801 class ReaderIOResultBasedN( @@ -112,9 +112,7 @@ class ReaderIOResultBasedN( __slots__ = () - _laws: ClassVar[Sequence[Law]] = ( - Law2(_LawSpec.asking_law), - ) + _laws: ClassVar[Sequence[Law]] = (Law2(_LawSpec.asking_law),) #: Type alias for kinds with three type arguments. diff --git a/returns/interfaces/specific/reader_result.py b/returns/interfaces/specific/reader_result.py index bc1599594..1be4e32e3 100644 --- a/returns/interfaces/specific/reader_result.py +++ b/returns/interfaces/specific/reader_result.py @@ -58,7 +58,7 @@ def bind_context_result( @classmethod @abstractmethod def from_failed_context( - cls: type[_ReaderResultLikeType], # noqa: N805 + cls: type[_ReaderResultLikeType], inner_value: Reader[_ErrorType, _EnvType], ) -> KindN[_ReaderResultLikeType, _FirstType, _ErrorType, _EnvType]: """Unit method to create new containers from failed ``Reader``.""" @@ -66,7 +66,7 @@ def from_failed_context( @classmethod @abstractmethod def from_result_context( - cls: type[_ReaderResultLikeType], # noqa: N805 + cls: type[_ReaderResultLikeType], inner_value: ReaderResult[_ValueType, _ErrorType, _EnvType], ) -> KindN[_ReaderResultLikeType, _ValueType, _ErrorType, _EnvType]: """Unit method to create new containers from ``ReaderResult``.""" @@ -100,9 +100,9 @@ def asking_law( env: _ThirdType, ) -> None: """Asking for an env, always returns the env.""" - assert container.ask().__call__( # noqa: WPS609 + assert container.ask().__call__( # noqa: PLC2801 env, - ) == container.from_value(env).__call__(env) # noqa: WPS609 + ) == container.from_value(env).__call__(env) # noqa: PLC2801 class ReaderResultBasedN( diff --git a/returns/interfaces/specific/result.py b/returns/interfaces/specific/result.py index 0c38d367b..420c3a0a1 100644 --- a/returns/interfaces/specific/result.py +++ b/returns/interfaces/specific/result.py @@ -56,7 +56,7 @@ def bind_result( @classmethod @abstractmethod def from_result( - cls: type[_ResultLikeType], # noqa: N805 + cls: type[_ResultLikeType], inner_value: Result[_ValueType, _ErrorType], ) -> KindN[_ResultLikeType, _ValueType, _ErrorType, _ThirdType]: """Unit method to create new containers from any raw value.""" diff --git a/returns/interfaces/swappable.py b/returns/interfaces/swappable.py index c48f34697..84c6ceadf 100644 --- a/returns/interfaces/swappable.py +++ b/returns/interfaces/swappable.py @@ -52,9 +52,7 @@ class SwappableN( __slots__ = () - _laws: ClassVar[Sequence[Law]] = ( - Law1(_LawSpec.double_swap_law), - ) + _laws: ClassVar[Sequence[Law]] = (Law1(_LawSpec.double_swap_law),) @abstractmethod def swap( diff --git a/returns/io.py b/returns/io.py index 3cb4cb59d..53933157a 100644 --- a/returns/io.py +++ b/returns/io.py @@ -1,4 +1,4 @@ -from abc import ABCMeta +from abc import ABC from collections.abc import Callable, Generator, Iterator from functools import wraps from inspect import FrameInfo @@ -18,20 +18,20 @@ ) from returns.result import Failure, Result, Success -_ValueType = TypeVar('_ValueType', covariant=True) +_ValueType_co = TypeVar('_ValueType_co', covariant=True) _NewValueType = TypeVar('_NewValueType') _FuncParams = ParamSpec('_FuncParams') # Result related: -_ErrorType = TypeVar('_ErrorType', covariant=True) +_ErrorType_co = TypeVar('_ErrorType_co', covariant=True) _NewErrorType = TypeVar('_NewErrorType') class IO( # type: ignore[type-var] BaseContainer, - SupportsKind1['IO', _ValueType], - io.IOLike1[_ValueType], + SupportsKind1['IO', _ValueType_co], + io.IOLike1[_ValueType_co], ): """ Explicit container for impure function results. @@ -60,12 +60,12 @@ class IO( # type: ignore[type-var] __slots__ = () - _inner_value: _ValueType + _inner_value: _ValueType_co #: Typesafe equality comparison with other `Result` objects. equals = container_equality - def __init__(self, inner_value: _ValueType) -> None: + def __init__(self, inner_value: _ValueType_co) -> None: """ Public constructor for this type. Also required for typing. @@ -79,7 +79,7 @@ def __init__(self, inner_value: _ValueType) -> None: def map( self, - function: Callable[[_ValueType], _NewValueType], + function: Callable[[_ValueType_co], _NewValueType], ) -> 'IO[_NewValueType]': """ Applies function to the inner value. @@ -101,7 +101,7 @@ def map( def apply( self, - container: Kind1['IO', Callable[[_ValueType], _NewValueType]], + container: Kind1['IO', Callable[[_ValueType_co], _NewValueType]], ) -> 'IO[_NewValueType]': """ Calls a wrapped function in a container on this container. @@ -125,11 +125,11 @@ def apply( >>> assert IO('b').apply(IO('a').apply(IO(appliable))) == IO('ab') """ - return self.map(dekind(container)._inner_value) # noqa: WPS437 + return self.map(dekind(container)._inner_value) # noqa: SLF001 def bind( self, - function: Callable[[_ValueType], Kind1['IO', _NewValueType]], + function: Callable[[_ValueType_co], Kind1['IO', _NewValueType]], ) -> 'IO[_NewValueType]': """ Applies 'function' to the result of a previous calculation. @@ -150,7 +150,7 @@ def bind( #: Alias for `bind` method. Part of the `IOLikeN` interface. bind_io = bind - def __iter__(self) -> Iterator[_ValueType]: + def __iter__(self) -> Iterator[_ValueType_co]: """API for :ref:`do-notation`.""" yield self._inner_value @@ -226,11 +226,12 @@ def from_ioresult( Is the reverse of :meth:`returns.io.IOResult.from_typecast`. """ - return IO(inner_value._inner_value) # noqa: WPS437 + return IO(inner_value._inner_value) # noqa: SLF001 # Helper functions: + def impure( function: Callable[_FuncParams, _NewValueType], ) -> Callable[_FuncParams, IO[_NewValueType]]: @@ -253,22 +254,25 @@ def impure( >>> assert function(1) == IO(2) """ + @wraps(function) def decorator( *args: _FuncParams.args, **kwargs: _FuncParams.kwargs, ) -> IO[_NewValueType]: return IO(function(*args, **kwargs)) + return decorator # IO and Result: + class IOResult( # type: ignore[type-var] BaseContainer, - SupportsKind2['IOResult', _ValueType, _ErrorType], - ioresult.IOResultBased2[_ValueType, _ErrorType], - metaclass=ABCMeta, + SupportsKind2['IOResult', _ValueType_co, _ErrorType_co], + ioresult.IOResultBased2[_ValueType_co, _ErrorType_co], + ABC, ): """ Explicit container for impure function results that might fail. @@ -327,13 +331,15 @@ class IOResult( # type: ignore[type-var] __slots__ = () - _inner_value: Result[_ValueType, _ErrorType] + _inner_value: Result[_ValueType_co, _ErrorType_co] __match_args__ = ('_inner_value',) #: Typesafe equality comparison with other `IOResult` objects. equals = container_equality - def __init__(self, inner_value: Result[_ValueType, _ErrorType]) -> None: + def __init__( + self, inner_value: Result[_ValueType_co, _ErrorType_co] + ) -> None: """ Private type constructor. @@ -355,14 +361,14 @@ def __repr__(self) -> str: '>' """ - return ''.format(self._inner_value) + return f'' @property def trace(self) -> list[FrameInfo] | None: """Returns a stack trace when :func:`~IOFailure` was called.""" return self._inner_value.trace - def swap(self) -> 'IOResult[_ErrorType, _ValueType]': + def swap(self) -> 'IOResult[_ErrorType_co, _ValueType_co]': """ Swaps value and error types. @@ -381,8 +387,9 @@ def swap(self) -> 'IOResult[_ErrorType, _ValueType]': return self.from_result(self._inner_value.swap()) def map( - self, function: Callable[[_ValueType], _NewValueType], - ) -> 'IOResult[_NewValueType, _ErrorType]': + self, + function: Callable[[_ValueType_co], _NewValueType], + ) -> 'IOResult[_NewValueType, _ErrorType_co]': """ Composes successful container with a pure function. @@ -398,10 +405,10 @@ def apply( self, container: Kind2[ 'IOResult', - Callable[[_ValueType], _NewValueType], - _ErrorType, + Callable[[_ValueType_co], _NewValueType], + _ErrorType_co, ], - ) -> 'IOResult[_NewValueType, _ErrorType]': + ) -> 'IOResult[_NewValueType, _ErrorType_co]': """ Calls a wrapped function in a container on this container. @@ -428,7 +435,7 @@ def apply( if isinstance(container, IOSuccess): return self.from_result( self._inner_value.map( - container.unwrap()._inner_value, # noqa: WPS437 + container.unwrap()._inner_value, # noqa: SLF001 ), ) return container # type: ignore @@ -436,10 +443,10 @@ def apply( def bind( self, function: Callable[ - [_ValueType], - Kind2['IOResult', _NewValueType, _ErrorType], + [_ValueType_co], + Kind2['IOResult', _NewValueType, _ErrorType_co], ], - ) -> 'IOResult[_NewValueType, _ErrorType]': + ) -> 'IOResult[_NewValueType, _ErrorType_co]': """ Composes successful container with a function that returns a container. @@ -463,10 +470,10 @@ def bind( def bind_result( self, function: Callable[ - [_ValueType], - Result[_NewValueType, _ErrorType], + [_ValueType_co], + Result[_NewValueType, _ErrorType_co], ], - ) -> 'IOResult[_NewValueType, _ErrorType]': + ) -> 'IOResult[_NewValueType, _ErrorType_co]': """ Composes successful container with a function that returns a container. @@ -492,8 +499,8 @@ def bind_result( def bind_io( self, - function: Callable[[_ValueType], IO[_NewValueType]], - ) -> 'IOResult[_NewValueType, _ErrorType]': + function: Callable[[_ValueType_co], IO[_NewValueType]], + ) -> 'IOResult[_NewValueType, _ErrorType_co]': """ Composes successful container with a function that returns a container. @@ -514,8 +521,8 @@ def bind_io( def alt( self, - function: Callable[[_ErrorType], _NewErrorType], - ) -> 'IOResult[_ValueType, _NewErrorType]': + function: Callable[[_ErrorType_co], _NewErrorType], + ) -> 'IOResult[_ValueType_co, _NewErrorType]': """ Composes failed container with a pure function to modify failure. @@ -530,10 +537,10 @@ def alt( def lash( self, function: Callable[ - [_ErrorType], - Kind2['IOResult', _ValueType, _NewErrorType], + [_ErrorType_co], + Kind2['IOResult', _ValueType_co, _NewErrorType], ], - ) -> 'IOResult[_ValueType, _NewErrorType]': + ) -> 'IOResult[_ValueType_co, _NewErrorType]': """ Composes failed container with a function that returns a container. @@ -554,7 +561,7 @@ def lash( def value_or( self, default_value: _NewValueType, - ) -> IO[_ValueType | _NewValueType]: + ) -> IO[_ValueType_co | _NewValueType]: """ Get value from successful container or default value from failed one. @@ -567,7 +574,7 @@ def value_or( """ return IO(self._inner_value.value_or(default_value)) - def unwrap(self) -> IO[_ValueType]: + def unwrap(self) -> IO[_ValueType_co]: """ Get value from successful container or raise exception for failed one. @@ -582,10 +589,10 @@ def unwrap(self) -> IO[_ValueType]: ... returns.primitives.exceptions.UnwrapFailedError - """ # noqa: RST307 + """ return IO(self._inner_value.unwrap()) - def failure(self) -> IO[_ErrorType]: + def failure(self) -> IO[_ErrorType_co]: """ Get failed value from failed container or raise exception from success. @@ -600,16 +607,16 @@ def failure(self) -> IO[_ErrorType]: ... returns.primitives.exceptions.UnwrapFailedError - """ # noqa: RST307 + """ return IO(self._inner_value.failure()) def compose_result( self, function: Callable[ - [Result[_ValueType, _ErrorType]], - Kind2['IOResult', _NewValueType, _ErrorType], + [Result[_ValueType_co, _ErrorType_co]], + Kind2['IOResult', _NewValueType, _ErrorType_co], ], - ) -> 'IOResult[_NewValueType, _ErrorType]': + ) -> 'IOResult[_NewValueType, _ErrorType_co]': """ Composes inner ``Result`` with ``IOResult`` returning function. @@ -631,10 +638,10 @@ def compose_result( """ return dekind(function(self._inner_value)) - def __iter__(self) -> Iterator[_ValueType]: + def __iter__(self) -> Iterator[_ValueType_co]: """API for :ref:`do-notation`.""" # We also unwrap `IO` here. - yield self.unwrap()._inner_value # noqa: WPS437 + yield self.unwrap()._inner_value # noqa: SLF001 @classmethod def do( @@ -671,14 +678,15 @@ def do( @classmethod def from_typecast( - cls, inner_value: IO[Result[_NewValueType, _NewErrorType]], + cls, + inner_value: IO[Result[_NewValueType, _NewErrorType]], ) -> 'IOResult[_NewValueType, _NewErrorType]': """ - Converts ``IO[Result[_ValueType, _ErrorType]]`` to ``IOResult``. + Converts ``IO[Result[_ValueType_co, _ErrorType_co]]`` to ``IOResult``. Also prevails the type of ``Result`` to ``IOResult``, so: - ``IO[Result[_ValueType, _ErrorType]]`` would become - ``IOResult[_ValueType, _ErrorType]``. + ``IO[Result[_ValueType_co, _ErrorType_co]]`` would become + ``IOResult[_ValueType_co, _ErrorType_co]``. .. code:: python @@ -689,11 +697,12 @@ def from_typecast( Can be reverted via :meth:`returns.io.IO.from_ioresult` method. """ - return cls.from_result(inner_value._inner_value) # noqa: WPS437 + return cls.from_result(inner_value._inner_value) # noqa: SLF001 @classmethod def from_failed_io( - cls, inner_value: IO[_NewErrorType], + cls, + inner_value: IO[_NewErrorType], ) -> 'IOResult[Any, _NewErrorType]': """ Creates new ``IOResult`` from "failed" ``IO`` container. @@ -705,11 +714,12 @@ def from_failed_io( >>> assert IOResult.from_failed_io(container) == IOFailure(1) """ - return IOFailure(inner_value._inner_value) # noqa: WPS437 + return IOFailure(inner_value._inner_value) # noqa: SLF001 @classmethod def from_io( - cls, inner_value: IO[_NewValueType], + cls, + inner_value: IO[_NewValueType], ) -> 'IOResult[_NewValueType, Any]': """ Creates new ``IOResult`` from "successful" ``IO`` container. @@ -721,11 +731,12 @@ def from_io( >>> assert IOResult.from_io(container) == IOSuccess(1) """ - return IOSuccess(inner_value._inner_value) # noqa: WPS437 + return IOSuccess(inner_value._inner_value) # noqa: SLF001 @classmethod def from_result( - cls, inner_value: Result[_NewValueType, _NewErrorType], + cls, + inner_value: Result[_NewValueType, _NewErrorType], ) -> 'IOResult[_NewValueType, _NewErrorType]': """ Creates ``IOResult`` from ``Result`` value. @@ -740,12 +751,13 @@ def from_result( """ if isinstance(inner_value, Success): - return IOSuccess(inner_value._inner_value) # noqa: WPS437 - return IOFailure(inner_value._inner_value) # type: ignore[arg-type] # noqa: WPS437, E501 + return IOSuccess(inner_value._inner_value) # noqa: SLF001 + return IOFailure(inner_value._inner_value) # type: ignore[arg-type] # noqa: SLF001 @classmethod def from_ioresult( - cls, inner_value: 'IOResult[_NewValueType, _NewErrorType]', + cls, + inner_value: 'IOResult[_NewValueType, _NewErrorType]', ) -> 'IOResult[_NewValueType, _NewErrorType]': """ Creates ``IOResult`` from existing ``IOResult`` value. @@ -762,7 +774,8 @@ def from_ioresult( @classmethod def from_value( - cls, inner_value: _NewValueType, + cls, + inner_value: _NewValueType, ) -> 'IOResult[_NewValueType, Any]': """ One more value to create success unit values. @@ -782,7 +795,8 @@ def from_value( @classmethod def from_failure( - cls, inner_value: _NewErrorType, + cls, + inner_value: _NewErrorType, ) -> 'IOResult[Any, _NewErrorType]': """ One more value to create failure unit values. @@ -802,18 +816,19 @@ def from_failure( @final -class IOFailure(IOResult[Any, _ErrorType]): +class IOFailure(IOResult[Any, _ErrorType_co]): """``IOFailure`` representation.""" __slots__ = () - _inner_value: Result[Any, _ErrorType] + _inner_value: Result[Any, _ErrorType_co] - def __init__(self, inner_value: _ErrorType) -> None: - """IOFailure constructor.""" # noqa: D403 + def __init__(self, inner_value: _ErrorType_co) -> None: + """IOFailure constructor.""" super().__init__(Failure(inner_value)) if not TYPE_CHECKING: # noqa: WPS604 # pragma: no branch + def bind(self, function): """Does nothing for ``IOFailure``.""" return self @@ -835,18 +850,19 @@ def lash(self, function): @final -class IOSuccess(IOResult[_ValueType, Any]): +class IOSuccess(IOResult[_ValueType_co, Any]): """``IOSuccess`` representation.""" __slots__ = () - _inner_value: Result[_ValueType, Any] + _inner_value: Result[_ValueType_co, Any] - def __init__(self, inner_value: _ValueType) -> None: - """IOSuccess constructor.""" # noqa: D403 + def __init__(self, inner_value: _ValueType_co) -> None: + """IOSuccess constructor.""" super().__init__(Success(inner_value)) if not TYPE_CHECKING: # noqa: WPS604 # pragma: no branch + def bind(self, function): """Composes this container with a function returning ``IOResult``.""" # noqa: E501 return function(self._inner_value.unwrap()) @@ -866,11 +882,12 @@ def lash(self, function): """Does nothing for ``IOSuccess``.""" return self + # Aliases: -#: Alias for ``IOResult[_ValueType, Exception]``. -IOResultE: TypeAlias = IOResult[_ValueType, Exception] +#: Alias for ``IOResult[_ValueType_co, Exception]``. +IOResultE: TypeAlias = IOResult[_ValueType_co, Exception] # impure_safe decorator: @@ -882,8 +899,7 @@ def lash(self, function): def impure_safe( function: Callable[_FuncParams, _NewValueType], /, -) -> Callable[_FuncParams, IOResultE[_NewValueType]]: - """Decorator to convert exception-throwing for any kind of Exception.""" +) -> Callable[_FuncParams, IOResultE[_NewValueType]]: ... @overload @@ -892,18 +908,16 @@ def impure_safe( ) -> Callable[ [Callable[_FuncParams, _NewValueType]], Callable[_FuncParams, IOResult[_NewValueType, _ExceptionType]], -]: - """Decorator to convert exception-throwing just for a set of Exceptions.""" +]: ... -def impure_safe( # noqa: WPS234, C901 +def impure_safe( # noqa: WPS234 exceptions: ( - Callable[_FuncParams, _NewValueType] | - tuple[type[_ExceptionType], ...] + Callable[_FuncParams, _NewValueType] | tuple[type[_ExceptionType], ...] ), ) -> ( - Callable[_FuncParams, IOResultE[_NewValueType]] | - Callable[ + Callable[_FuncParams, IOResultE[_NewValueType]] + | Callable[ [Callable[_FuncParams, _NewValueType]], Callable[_FuncParams, IOResult[_NewValueType, _ExceptionType]], ] @@ -949,6 +963,7 @@ def impure_safe( # noqa: WPS234, C901 Similar to :func:`returns.future.future_safe` and :func:`returns.result.safe` decorators. """ + def factory( inner_function: Callable[_FuncParams, _NewValueType], inner_exceptions: tuple[type[_ExceptionType], ...], @@ -962,6 +977,7 @@ def decorator( return IOSuccess(inner_function(*args, **kwargs)) except inner_exceptions as exc: return IOFailure(exc) + return decorator if isinstance(exceptions, tuple): diff --git a/returns/iterables.py b/returns/iterables.py index b6084a8b9..919d5ebca 100644 --- a/returns/iterables.py +++ b/returns/iterables.py @@ -1,6 +1,6 @@ from abc import abstractmethod from collections.abc import Callable, Iterable -from typing import Tuple, TypeVar, final +from typing import TypeVar, final from returns.interfaces.applicative import ApplicativeN from returns.interfaces.failable import FailableN @@ -100,13 +100,13 @@ def collect( ], acc: KindN[ _ApplicativeKind, - 'Tuple[_FirstType, ...]', + 'tuple[_FirstType, ...]', _SecondType, _ThirdType, ], ) -> KindN[ _ApplicativeKind, - 'Tuple[_FirstType, ...]', + 'tuple[_FirstType, ...]', _SecondType, _ThirdType, ]: @@ -165,13 +165,13 @@ def collect_all( ], acc: KindN[ _FailableKind, - 'Tuple[_FirstType, ...]', + 'tuple[_FirstType, ...]', _SecondType, _ThirdType, ], ) -> KindN[ _FailableKind, - 'Tuple[_FirstType, ...]', + 'tuple[_FirstType, ...]', _SecondType, _ThirdType, ]: @@ -265,13 +265,13 @@ def _collect( ], acc: KindN[ _ApplicativeKind, - 'Tuple[_FirstType, ...]', + 'tuple[_FirstType, ...]', _SecondType, _ThirdType, ], ) -> KindN[ _ApplicativeKind, - 'Tuple[_FirstType, ...]', + 'tuple[_FirstType, ...]', _SecondType, _ThirdType, ]: @@ -290,13 +290,13 @@ def _collect_all( ], acc: KindN[ _FailableKind, - 'Tuple[_FirstType, ...]', + 'tuple[_FirstType, ...]', _SecondType, _ThirdType, ], ) -> KindN[ _FailableKind, - 'Tuple[_FirstType, ...]', + 'tuple[_FirstType, ...]', _SecondType, _ThirdType, ]: @@ -359,11 +359,12 @@ def _loop( # Helper functions # ================ + def _concat_sequence( first: _FirstType, ) -> Callable[ - ['Tuple[_FirstType, ...]'], - 'Tuple[_FirstType, ...]', + ['tuple[_FirstType, ...]'], + 'tuple[_FirstType, ...]', ]: """ Concats a given item to an existing sequence. @@ -372,15 +373,21 @@ def _concat_sequence( ``@curry`` decorator is way slower. And we don't need its features here. But, your functions can use ``@curry`` if you need it. """ - return lambda second: second + (first,) + return lambda second: (*second, first) def _concat_applicative( current: KindN[ - _ApplicativeKind, _FirstType, _SecondType, _ThirdType, + _ApplicativeKind, + _FirstType, + _SecondType, + _ThirdType, ], acc: KindN[ - _ApplicativeKind, _UpdatedType, _SecondType, _ThirdType, + _ApplicativeKind, + _UpdatedType, + _SecondType, + _ThirdType, ], function: KindN[ _ApplicativeKind, @@ -395,10 +402,16 @@ def _concat_applicative( def _concat_failable_safely( current: KindN[ - _FailableKind, _FirstType, _SecondType, _ThirdType, + _FailableKind, + _FirstType, + _SecondType, + _ThirdType, ], acc: KindN[ - _FailableKind, _UpdatedType, _SecondType, _ThirdType, + _FailableKind, + _UpdatedType, + _SecondType, + _ThirdType, ], function: KindN[ _FailableKind, diff --git a/returns/maybe.py b/returns/maybe.py index 088ff05ed..1e04a3e20 100644 --- a/returns/maybe.py +++ b/returns/maybe.py @@ -1,4 +1,4 @@ -from abc import ABCMeta +from abc import ABC from collections.abc import Callable, Generator, Iterator from functools import wraps from typing import TYPE_CHECKING, Any, ClassVar, Optional, TypeVar, final @@ -11,7 +11,7 @@ from returns.primitives.hkt import Kind1, SupportsKind1 # Definitions: -_ValueType = TypeVar('_ValueType', covariant=True) +_ValueType_co = TypeVar('_ValueType_co', covariant=True) _NewValueType = TypeVar('_NewValueType') _FuncParams = ParamSpec('_FuncParams') @@ -19,9 +19,9 @@ class Maybe( # type: ignore[type-var] BaseContainer, - SupportsKind1['Maybe', _ValueType], - MaybeBased2[_ValueType, None], - metaclass=ABCMeta, + SupportsKind1['Maybe', _ValueType_co], + MaybeBased2[_ValueType_co, None], + ABC, ): """ Represents a result of a series of computations that can return ``None``. @@ -37,7 +37,7 @@ class Maybe( # type: ignore[type-var] __slots__ = () - _inner_value: _ValueType | None + _inner_value: _ValueType_co | None __match_args__ = ('_inner_value',) #: Alias for `Nothing` @@ -48,7 +48,7 @@ class Maybe( # type: ignore[type-var] def map( self, - function: Callable[[_ValueType], _NewValueType], + function: Callable[[_ValueType_co], _NewValueType], ) -> 'Maybe[_NewValueType]': """ Composes successful container with a pure function. @@ -66,7 +66,7 @@ def map( def apply( self, - function: Kind1['Maybe', Callable[[_ValueType], _NewValueType]], + function: Kind1['Maybe', Callable[[_ValueType_co], _NewValueType]], ) -> 'Maybe[_NewValueType]': """ Calls a wrapped function in a container on this container. @@ -87,7 +87,7 @@ def apply( def bind( self, - function: Callable[[_ValueType], Kind1['Maybe', _NewValueType]], + function: Callable[[_ValueType_co], Kind1['Maybe', _NewValueType]], ) -> 'Maybe[_NewValueType]': """ Composes successful container with a function that returns a container. @@ -105,7 +105,7 @@ def bind( def bind_optional( self, - function: Callable[[_ValueType], _NewValueType | None], + function: Callable[[_ValueType_co], _NewValueType | None], ) -> 'Maybe[_NewValueType]': """ Binds a function returning an optional value over a container. @@ -125,8 +125,8 @@ def bind_optional( def lash( self, - function: Callable[[Any], Kind1['Maybe', _ValueType]], - ) -> 'Maybe[_ValueType]': + function: Callable[[Any], Kind1['Maybe', _ValueType_co]], + ) -> 'Maybe[_ValueType_co]': """ Composes failed container with a function that returns a container. @@ -145,7 +145,7 @@ def lash( """ - def __iter__(self) -> Iterator[_ValueType]: + def __iter__(self) -> Iterator[_ValueType_co]: """API for :ref:`do-notation`.""" yield self.unwrap() @@ -184,7 +184,7 @@ def do( def value_or( self, default_value: _NewValueType, - ) -> _ValueType | _NewValueType: + ) -> _ValueType_co | _NewValueType: """ Get value from successful container or default value from failed one. @@ -199,7 +199,7 @@ def value_or( def or_else_call( self, function: Callable[[], _NewValueType], - ) -> _ValueType | _NewValueType: + ) -> _ValueType_co | _NewValueType: """ Get value from successful container or default value from failed one. @@ -233,7 +233,7 @@ def or_else_call( """ - def unwrap(self) -> _ValueType: + def unwrap(self) -> _ValueType_co: """ Get value from successful container or raise exception for failed one. @@ -248,7 +248,7 @@ def unwrap(self) -> _ValueType: ... returns.primitives.exceptions.UnwrapFailedError - """ # noqa: RST307 + """ def failure(self) -> None: """ @@ -265,11 +265,12 @@ def failure(self) -> None: ... returns.primitives.exceptions.UnwrapFailedError - """ # noqa: RST307 + """ @classmethod def from_value( - cls, inner_value: _NewValueType, + cls, + inner_value: _NewValueType, ) -> 'Maybe[_NewValueType]': """ Creates new instance of ``Maybe`` container based on a value. @@ -285,7 +286,8 @@ def from_value( @classmethod def from_optional( - cls, inner_value: _NewValueType | None, + cls, + inner_value: _NewValueType | None, ) -> 'Maybe[_NewValueType]': """ Creates new instance of ``Maybe`` container based on an optional value. @@ -313,7 +315,7 @@ class _Nothing(Maybe[Any]): def __new__(cls, *args: Any, **kwargs: Any) -> '_Nothing': if cls._instance is None: - cls._instance = object.__new__(cls) # noqa: WPS609 + cls._instance = object.__new__(cls) return cls._instance def __init__(self, inner_value: None = None) -> None: # noqa: WPS632 @@ -378,7 +380,7 @@ def failure(self) -> None: @final -class Some(Maybe[_ValueType]): +class Some(Maybe[_ValueType_co]): """ Represents a calculation which has succeeded and contains the value. @@ -387,13 +389,14 @@ class Some(Maybe[_ValueType]): __slots__ = () - _inner_value: _ValueType + _inner_value: _ValueType_co - def __init__(self, inner_value: _ValueType) -> None: + def __init__(self, inner_value: _ValueType_co) -> None: """Some constructor.""" super().__init__(inner_value) if not TYPE_CHECKING: # noqa: WPS604 # pragma: no branch + def bind(self, function): """Binds current container to a function that returns container.""" return function(self._inner_value) @@ -439,8 +442,8 @@ def failure(self): def maybe( - function: Callable[_FuncParams, _ValueType | None], -) -> Callable[_FuncParams, Maybe[_ValueType]]: + function: Callable[_FuncParams, _ValueType_co | None], +) -> Callable[_FuncParams, Maybe[_ValueType_co]]: """ Decorator to convert ``None``-returning function to ``Maybe`` container. @@ -461,10 +464,12 @@ def maybe( >>> assert might_be_none(1) == Some(1.0) """ + @wraps(function) def decorator( *args: _FuncParams.args, **kwargs: _FuncParams.kwargs, - ) -> Maybe[_ValueType]: + ) -> Maybe[_ValueType_co]: return Maybe.from_optional(function(*args, **kwargs)) + return decorator diff --git a/returns/methods/cond.py b/returns/methods/cond.py index 032227b0d..432a6f17a 100644 --- a/returns/methods/cond.py +++ b/returns/methods/cond.py @@ -14,27 +14,23 @@ @overload def internal_cond( container_type: type[_SingleFailableKind], - is_success: bool, + is_success: bool, # noqa: FBT001 success_value: _ValueType, -) -> KindN[_SingleFailableKind, _ValueType, _ErrorType, NoDeps]: - """Reduce the boilerplate when choosing paths with ``SingleFailableN``.""" +) -> KindN[_SingleFailableKind, _ValueType, _ErrorType, NoDeps]: ... @overload def internal_cond( container_type: type[_DiverseFailableKind], - is_success: bool, + is_success: bool, # noqa: FBT001 success_value: _ValueType, error_value: _ErrorType, -) -> KindN[_DiverseFailableKind, _ValueType, _ErrorType, NoDeps]: - """Reduce the boilerplate when choosing paths with ``DiverseFailableN``.""" +) -> KindN[_DiverseFailableKind, _ValueType, _ErrorType, NoDeps]: ... def internal_cond( - container_type: ( - type[_SingleFailableKind] | type[_DiverseFailableKind] - ), - is_success: bool, + container_type: (type[_SingleFailableKind] | type[_DiverseFailableKind]), + is_success: bool, # noqa: FBT001 success_value: _ValueType, error_value: _ErrorType | None = None, ): diff --git a/returns/methods/partition.py b/returns/methods/partition.py index 00f2c4b10..fec9ed096 100644 --- a/returns/methods/partition.py +++ b/returns/methods/partition.py @@ -4,15 +4,13 @@ from returns.interfaces.unwrappable import Unwrappable from returns.primitives.exceptions import UnwrapFailedError -_ValueType = TypeVar('_ValueType', covariant=True) -_ErrorType = TypeVar('_ErrorType', covariant=True) +_ValueType_co = TypeVar('_ValueType_co', covariant=True) +_ErrorType_co = TypeVar('_ErrorType_co', covariant=True) def partition( - containers: Iterable[ - Unwrappable[_ValueType, _ErrorType], - ], -) -> tuple[list[_ValueType], list[_ErrorType]]: + containers: Iterable[Unwrappable[_ValueType_co, _ErrorType_co],], +) -> tuple[list[_ValueType_co], list[_ErrorType_co]]: """ Partition a list of unwrappables into successful and failed values. @@ -28,11 +26,11 @@ def partition( ([1, 3], [2, 4]) """ - successes: list[_ValueType] = [] - failures: list[_ErrorType] = [] + successes: list[_ValueType_co] = [] + failures: list[_ErrorType_co] = [] for container in containers: try: successes.append(container.unwrap()) - except UnwrapFailedError: + except UnwrapFailedError: # noqa: PERF203 failures.append(container.failure()) return successes, failures diff --git a/returns/pointfree/alt.py b/returns/pointfree/alt.py index dd1222bb5..e8ba7b230 100644 --- a/returns/pointfree/alt.py +++ b/returns/pointfree/alt.py @@ -14,10 +14,12 @@ def alt( function: Callable[[_SecondType], _UpdatedType], -) -> Kinded[Callable[ - [KindN[_AltableKind, _FirstType, _SecondType, _ThirdType]], - KindN[_AltableKind, _FirstType, _UpdatedType, _ThirdType], -]]: +) -> Kinded[ + Callable[ + [KindN[_AltableKind, _FirstType, _SecondType, _ThirdType]], + KindN[_AltableKind, _FirstType, _UpdatedType, _ThirdType], + ] +]: """ Lifts function to be wrapped in a container for better composition. @@ -44,9 +46,11 @@ def alt( See :class:`returns.primitives.interfaces.altable.AltableN` for more info. """ + @kinded def factory( container: KindN[_AltableKind, _FirstType, _SecondType, _ThirdType], ) -> KindN[_AltableKind, _FirstType, _UpdatedType, _ThirdType]: return container.alt(function) + return factory diff --git a/returns/pointfree/apply.py b/returns/pointfree/apply.py index 471ca0a42..583103e87 100644 --- a/returns/pointfree/apply.py +++ b/returns/pointfree/apply.py @@ -19,10 +19,12 @@ def apply( _SecondType, _ThirdType, ], -) -> Kinded[Callable[ - [KindN[_ApplicativeKind, _FirstType, _SecondType, _ThirdType]], - KindN[_ApplicativeKind, _UpdatedType, _SecondType, _ThirdType], -]]: +) -> Kinded[ + Callable[ + [KindN[_ApplicativeKind, _FirstType, _SecondType, _ThirdType]], + KindN[_ApplicativeKind, _UpdatedType, _SecondType, _ThirdType], + ] +]: """ Turns container containing a function into a callable. @@ -51,9 +53,11 @@ def apply( See :class:`returns.interfaces.applicative.ApplicativeN` for more info. """ + @kinded def factory( other: KindN[_ApplicativeKind, _FirstType, _SecondType, _ThirdType], ) -> KindN[_ApplicativeKind, _UpdatedType, _SecondType, _ThirdType]: return other.apply(container) + return factory diff --git a/returns/pointfree/bimap.py b/returns/pointfree/bimap.py index 59568418d..b7226b883 100644 --- a/returns/pointfree/bimap.py +++ b/returns/pointfree/bimap.py @@ -17,10 +17,12 @@ def bimap( on_first: Callable[[_FirstType], _UpdatedType1], on_second: Callable[[_SecondType], _UpdatedType2], -) -> Kinded[Callable[ - [KindN[_BiMappableKind, _FirstType, _SecondType, _ThirdType]], - KindN[_BiMappableKind, _UpdatedType1, _UpdatedType2, _ThirdType], -]]: +) -> Kinded[ + Callable[ + [KindN[_BiMappableKind, _FirstType, _SecondType, _ThirdType]], + KindN[_BiMappableKind, _UpdatedType1, _UpdatedType2, _ThirdType], + ] +]: """ Maps container on both: first and second arguments. @@ -48,9 +50,11 @@ def bimap( for more info. """ + @kinded def factory( container: KindN[_BiMappableKind, _FirstType, _SecondType, _ThirdType], ) -> KindN[_BiMappableKind, _UpdatedType1, _UpdatedType2, _ThirdType]: return container.map(on_first).alt(on_second) + return factory diff --git a/returns/pointfree/bind.py b/returns/pointfree/bind.py index 8e8e94a26..26e8e2584 100644 --- a/returns/pointfree/bind.py +++ b/returns/pointfree/bind.py @@ -17,10 +17,12 @@ def bind( [_FirstType], KindN[_BindableKind, _UpdatedType, _SecondType, _ThirdType], ], -) -> Kinded[Callable[ - [KindN[_BindableKind, _FirstType, _SecondType, _ThirdType]], - 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. @@ -49,9 +51,11 @@ def bind( 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 container.bind(function) + return factory diff --git a/returns/pointfree/bind_async.py b/returns/pointfree/bind_async.py index 7581206c4..564f3d305 100644 --- a/returns/pointfree/bind_async.py +++ b/returns/pointfree/bind_async.py @@ -17,10 +17,12 @@ def bind_async( [_FirstType], Awaitable[KindN[_FutureKind, _UpdatedType, _SecondType, _ThirdType]], ], -) -> Kinded[Callable[ - [KindN[_FutureKind, _FirstType, _SecondType, _ThirdType]], - KindN[_FutureKind, _UpdatedType, _SecondType, _ThirdType], -]]: +) -> Kinded[ + Callable[ + [KindN[_FutureKind, _FirstType, _SecondType, _ThirdType]], + KindN[_FutureKind, _UpdatedType, _SecondType, _ThirdType], + ] +]: """ Compose a container and ``async`` function returning a container. @@ -51,9 +53,11 @@ def bind_async( for more info. """ + @kinded def factory( container: KindN[_FutureKind, _FirstType, _SecondType, _ThirdType], ) -> KindN[_FutureKind, _UpdatedType, _SecondType, _ThirdType]: return container.bind_async(function) + return factory diff --git a/returns/pointfree/bind_async_context_future_result.py b/returns/pointfree/bind_async_context_future_result.py index 034f53213..41ef4df5c 100644 --- a/returns/pointfree/bind_async_context_future_result.py +++ b/returns/pointfree/bind_async_context_future_result.py @@ -25,10 +25,18 @@ def bind_async_context_future_result( [_FirstType], Awaitable['ReaderFutureResult[_UpdatedType, _SecondType, _ThirdType]'], ], -) -> Kinded[Callable[ - [KindN[_ReaderFutureResultLikeKind, _FirstType, _SecondType, _ThirdType]], - KindN[_ReaderFutureResultLikeKind, _UpdatedType, _SecondType, _ThirdType], -]]: +) -> Kinded[ + Callable[ + [ + KindN[ + _ReaderFutureResultLikeKind, _FirstType, _SecondType, _ThirdType + ] + ], + KindN[ + _ReaderFutureResultLikeKind, _UpdatedType, _SecondType, _ThirdType + ], + ] +]: """ Lifts function from ``RequiresContextFutureResult`` for better composition. @@ -59,6 +67,7 @@ def bind_async_context_future_result( ... )('abc').awaitable) == IOFailure(0) """ + @kinded def factory( container: KindN[ @@ -74,4 +83,5 @@ def factory( _ThirdType, ]: return container.bind_async_context_future_result(function) + return factory diff --git a/returns/pointfree/bind_async_future.py b/returns/pointfree/bind_async_future.py index f8987abeb..25f155eac 100644 --- a/returns/pointfree/bind_async_future.py +++ b/returns/pointfree/bind_async_future.py @@ -18,10 +18,12 @@ def bind_async_future( [_FirstType], Awaitable[Future[_UpdatedType]], ], -) -> Kinded[Callable[ - [KindN[_FutureKind, _FirstType, _SecondType, _ThirdType]], - KindN[_FutureKind, _UpdatedType, _SecondType, _ThirdType], -]]: +) -> Kinded[ + Callable[ + [KindN[_FutureKind, _FirstType, _SecondType, _ThirdType]], + KindN[_FutureKind, _UpdatedType, _SecondType, _ThirdType], + ] +]: """ Compose a container and async function returning ``Future``. @@ -53,9 +55,11 @@ def bind_async_future( for more info. """ + @kinded def factory( container: KindN[_FutureKind, _FirstType, _SecondType, _ThirdType], ) -> KindN[_FutureKind, _UpdatedType, _SecondType, _ThirdType]: return container.bind_async_future(function) + return factory diff --git a/returns/pointfree/bind_async_future_result.py b/returns/pointfree/bind_async_future_result.py index 7d6a36d34..8a25c8b20 100644 --- a/returns/pointfree/bind_async_future_result.py +++ b/returns/pointfree/bind_async_future_result.py @@ -18,10 +18,12 @@ def bind_async_future_result( [_FirstType], Awaitable[FutureResult[_UpdatedType, _SecondType]], ], -) -> Kinded[Callable[ - [KindN[_FutureResultKind, _FirstType, _SecondType, _ThirdType]], - KindN[_FutureResultKind, _UpdatedType, _SecondType, _ThirdType], -]]: +) -> Kinded[ + Callable[ + [KindN[_FutureResultKind, _FirstType, _SecondType, _ThirdType]], + KindN[_FutureResultKind, _UpdatedType, _SecondType, _ThirdType], + ] +]: """ Compose a container and async function returning ``FutureResult``. @@ -62,11 +64,16 @@ def bind_async_future_result( See :class:`~FutureResultLikeN` for more info. """ + @kinded def factory( container: KindN[ - _FutureResultKind, _FirstType, _SecondType, _ThirdType, + _FutureResultKind, + _FirstType, + _SecondType, + _ThirdType, ], ) -> KindN[_FutureResultKind, _UpdatedType, _SecondType, _ThirdType]: return container.bind_async_future_result(function) + return factory diff --git a/returns/pointfree/bind_awaitable.py b/returns/pointfree/bind_awaitable.py index 0ac7cdef3..6f5be6aae 100644 --- a/returns/pointfree/bind_awaitable.py +++ b/returns/pointfree/bind_awaitable.py @@ -14,10 +14,12 @@ def bind_awaitable( function: Callable[[_FirstType], Awaitable[_UpdatedType]], -) -> Kinded[Callable[ - [KindN[_FutureKind, _FirstType, _SecondType, _ThirdType]], - KindN[_FutureKind, _UpdatedType, _SecondType, _ThirdType], -]]: +) -> Kinded[ + Callable[ + [KindN[_FutureKind, _FirstType, _SecondType, _ThirdType]], + KindN[_FutureKind, _UpdatedType, _SecondType, _ThirdType], + ] +]: """ Composes a container a regular ``async`` function. @@ -51,9 +53,11 @@ def bind_awaitable( for more info. """ + @kinded def factory( container: KindN[_FutureKind, _FirstType, _SecondType, _ThirdType], ) -> KindN[_FutureKind, _UpdatedType, _SecondType, _ThirdType]: return container.bind_awaitable(function) + return factory diff --git a/returns/pointfree/bind_context.py b/returns/pointfree/bind_context.py index d3e7fcf6b..9a9020622 100644 --- a/returns/pointfree/bind_context.py +++ b/returns/pointfree/bind_context.py @@ -23,10 +23,12 @@ def bind_context2( [_FirstType], RequiresContext[_UpdatedType, _SecondType], ], -) -> Kinded[Callable[ - [Kind2[_Reader2Kind, _FirstType, _SecondType]], - Kind2[_Reader2Kind, _UpdatedType, _SecondType], -]]: +) -> Kinded[ + Callable[ + [Kind2[_Reader2Kind, _FirstType, _SecondType]], + Kind2[_Reader2Kind, _UpdatedType, _SecondType], + ] +]: """ Composes successful container with a function that returns a container. @@ -52,11 +54,13 @@ def bind_context2( for more info. """ + @kinded def factory( container: Kind2[_Reader2Kind, _FirstType, _SecondType], ) -> Kind2[_Reader2Kind, _UpdatedType, _SecondType]: return container.bind_context(function) + return factory @@ -65,10 +69,12 @@ def bind_context3( [_FirstType], RequiresContext[_UpdatedType, _ThirdType], ], -) -> Kinded[Callable[ - [Kind3[_Reader3Kind, _FirstType, _SecondType, _ThirdType]], - Kind3[_Reader3Kind, _UpdatedType, _SecondType, _ThirdType], -]]: +) -> Kinded[ + Callable[ + [Kind3[_Reader3Kind, _FirstType, _SecondType, _ThirdType]], + Kind3[_Reader3Kind, _UpdatedType, _SecondType, _ThirdType], + ] +]: """ Composes successful container with a function that returns a container. @@ -98,11 +104,13 @@ def bind_context3( for more info. """ + @kinded def factory( container: Kind3[_Reader3Kind, _FirstType, _SecondType, _ThirdType], ) -> Kind3[_Reader3Kind, _UpdatedType, _SecondType, _ThirdType]: return container.bind_context(function) + return factory diff --git a/returns/pointfree/bind_context_future_result.py b/returns/pointfree/bind_context_future_result.py index 33fa35a5b..8d44ec235 100644 --- a/returns/pointfree/bind_context_future_result.py +++ b/returns/pointfree/bind_context_future_result.py @@ -25,10 +25,18 @@ def bind_context_future_result( [_FirstType], 'ReaderFutureResult[_UpdatedType, _SecondType, _ThirdType]', ], -) -> Kinded[Callable[ - [KindN[_ReaderFutureResultLikeKind, _FirstType, _SecondType, _ThirdType]], - KindN[_ReaderFutureResultLikeKind, _UpdatedType, _SecondType, _ThirdType], -]]: +) -> Kinded[ + Callable[ + [ + KindN[ + _ReaderFutureResultLikeKind, _FirstType, _SecondType, _ThirdType + ] + ], + KindN[ + _ReaderFutureResultLikeKind, _UpdatedType, _SecondType, _ThirdType + ], + ] +]: """ Lifts function from ``RequiresContextFutureResult`` for better composition. @@ -59,6 +67,7 @@ def bind_context_future_result( ... )('abc').awaitable) == IOFailure(0) """ + @kinded def factory( container: KindN[ @@ -74,4 +83,5 @@ def factory( _ThirdType, ]: return container.bind_context_future_result(function) + return factory diff --git a/returns/pointfree/bind_context_ioresult.py b/returns/pointfree/bind_context_ioresult.py index 564ed15f4..4cf4990a3 100644 --- a/returns/pointfree/bind_context_ioresult.py +++ b/returns/pointfree/bind_context_ioresult.py @@ -25,10 +25,12 @@ def bind_context_ioresult( [_FirstType], ReaderIOResult[_UpdatedType, _SecondType, _ThirdType], ], -) -> Kinded[Callable[ - [KindN[_ReaderIOResultLikeKind, _FirstType, _SecondType, _ThirdType]], - KindN[_ReaderIOResultLikeKind, _UpdatedType, _SecondType, _ThirdType], -]]: +) -> Kinded[ + Callable[ + [KindN[_ReaderIOResultLikeKind, _FirstType, _SecondType, _ThirdType]], + KindN[_ReaderIOResultLikeKind, _UpdatedType, _SecondType, _ThirdType], + ] +]: """ Lifts function from ``RequiresContextIOResult`` for better composition. @@ -61,6 +63,7 @@ def bind_context_ioresult( ... )('abc').awaitable) == IOFailure(0) """ + @kinded def factory( container: KindN[ @@ -71,4 +74,5 @@ def factory( ], ) -> KindN[_ReaderIOResultLikeKind, _UpdatedType, _SecondType, _ThirdType]: return container.bind_context_ioresult(function) + return factory diff --git a/returns/pointfree/bind_context_result.py b/returns/pointfree/bind_context_result.py index 091f43051..b15cf373b 100644 --- a/returns/pointfree/bind_context_result.py +++ b/returns/pointfree/bind_context_result.py @@ -25,10 +25,12 @@ def bind_context_result( [_FirstType], ReaderResult[_UpdatedType, _SecondType, _ThirdType], ], -) -> Kinded[Callable[ - [KindN[_ReaderResultLikeKind, _FirstType, _SecondType, _ThirdType]], - KindN[_ReaderResultLikeKind, _UpdatedType, _SecondType, _ThirdType], -]]: +) -> Kinded[ + Callable[ + [KindN[_ReaderResultLikeKind, _FirstType, _SecondType, _ThirdType]], + KindN[_ReaderResultLikeKind, _UpdatedType, _SecondType, _ThirdType], + ] +]: """ Composes successful container with a function that returns a container. @@ -55,6 +57,7 @@ def bind_context_result( ... )(...) == IOFailure('a') """ + @kinded def factory( container: KindN[ @@ -65,4 +68,5 @@ def factory( ], ) -> KindN[_ReaderResultLikeKind, _UpdatedType, _SecondType, _ThirdType]: return container.bind_context_result(function) + return factory diff --git a/returns/pointfree/bind_future.py b/returns/pointfree/bind_future.py index 6b8e4b877..c784d917b 100644 --- a/returns/pointfree/bind_future.py +++ b/returns/pointfree/bind_future.py @@ -15,10 +15,12 @@ def bind_future( function: Callable[[_FirstType], Future[_UpdatedType]], -) -> Kinded[Callable[ - [KindN[_FutureKind, _FirstType, _SecondType, _ThirdType]], - KindN[_FutureKind, _UpdatedType, _SecondType, _ThirdType], -]]: +) -> Kinded[ + Callable[ + [KindN[_FutureKind, _FirstType, _SecondType, _ThirdType]], + KindN[_FutureKind, _UpdatedType, _SecondType, _ThirdType], + ] +]: """ Compose a container and sync function returning ``Future``. @@ -52,9 +54,11 @@ def bind_future( for more info. """ + @kinded def factory( container: KindN[_FutureKind, _FirstType, _SecondType, _ThirdType], ) -> KindN[_FutureKind, _UpdatedType, _SecondType, _ThirdType]: return container.bind_future(function) + return factory diff --git a/returns/pointfree/bind_future_result.py b/returns/pointfree/bind_future_result.py index ff765d8f2..ea5dc4c43 100644 --- a/returns/pointfree/bind_future_result.py +++ b/returns/pointfree/bind_future_result.py @@ -15,10 +15,12 @@ def bind_future_result( function: Callable[[_FirstType], FutureResult[_UpdatedType, _SecondType]], -) -> Kinded[Callable[ - [KindN[_FutureResultKind, _FirstType, _SecondType, _ThirdType]], - KindN[_FutureResultKind, _UpdatedType, _SecondType, _ThirdType], -]]: +) -> Kinded[ + Callable[ + [KindN[_FutureResultKind, _FirstType, _SecondType, _ThirdType]], + KindN[_FutureResultKind, _UpdatedType, _SecondType, _ThirdType], + ] +]: """ Compose a container and async function returning ``FutureResult``. @@ -59,11 +61,16 @@ def bind_future_result( See :class:`~FutureResultLikeN` for more info. """ + @kinded def factory( container: KindN[ - _FutureResultKind, _FirstType, _SecondType, _ThirdType, + _FutureResultKind, + _FirstType, + _SecondType, + _ThirdType, ], ) -> KindN[_FutureResultKind, _UpdatedType, _SecondType, _ThirdType]: return container.bind_future_result(function) + return factory diff --git a/returns/pointfree/bind_io.py b/returns/pointfree/bind_io.py index cff9730a9..4f357645b 100644 --- a/returns/pointfree/bind_io.py +++ b/returns/pointfree/bind_io.py @@ -9,20 +9,22 @@ if TYPE_CHECKING: from returns.io import IO # noqa: WPS433 -_FirstType = TypeVar('_FirstType', contravariant=True) +_FirstType_contra = TypeVar('_FirstType_contra', contravariant=True) _SecondType = TypeVar('_SecondType') -_ThirdType = TypeVar('_ThirdType', contravariant=True) -_UpdatedType = TypeVar('_UpdatedType', covariant=True) +_ThirdType_contra = TypeVar('_ThirdType_contra', contravariant=True) +_UpdatedType_co = TypeVar('_UpdatedType_co', covariant=True) _IOLikeKind = TypeVar('_IOLikeKind', bound=IOLikeN) def bind_io( - function: Callable[[_FirstType], IO[_UpdatedType]], -) -> Kinded[Callable[ - [KindN[_IOLikeKind, _FirstType, _SecondType, _ThirdType]], - KindN[_IOLikeKind, _UpdatedType, _SecondType, _ThirdType], -]]: + function: Callable[[_FirstType_contra], IO[_UpdatedType_co]], +) -> Kinded[ + Callable[ + [KindN[_IOLikeKind, _FirstType_contra, _SecondType, _ThirdType_contra]], + KindN[_IOLikeKind, _UpdatedType_co, _SecondType, _ThirdType_contra], + ] +]: """ Composes successful container with a function that returns a container. @@ -47,9 +49,13 @@ def bind_io( >>> assert bound(IOFailure(1)) == IOFailure(1) """ + @kinded def factory( - container: KindN[_IOLikeKind, _FirstType, _SecondType, _ThirdType], - ) -> KindN[_IOLikeKind, _UpdatedType, _SecondType, _ThirdType]: + container: KindN[ + _IOLikeKind, _FirstType_contra, _SecondType, _ThirdType_contra + ], + ) -> KindN[_IOLikeKind, _UpdatedType_co, _SecondType, _ThirdType_contra]: return container.bind_io(function) + return factory diff --git a/returns/pointfree/bind_ioresult.py b/returns/pointfree/bind_ioresult.py index 8a83e5cf1..da26a0f5d 100644 --- a/returns/pointfree/bind_ioresult.py +++ b/returns/pointfree/bind_ioresult.py @@ -19,10 +19,12 @@ def bind_ioresult( function: Callable[[_FirstType], IOResult[_UpdatedType, _SecondType]], -) -> Kinded[Callable[ - [KindN[_IOResultLikeKind, _FirstType, _SecondType, _ThirdType]], - KindN[_IOResultLikeKind, _UpdatedType, _SecondType, _ThirdType], -]]: +) -> Kinded[ + Callable[ + [KindN[_IOResultLikeKind, _FirstType, _SecondType, _ThirdType]], + KindN[_IOResultLikeKind, _UpdatedType, _SecondType, _ThirdType], + ] +]: """ Composes successful container with a function that returns a container. @@ -48,6 +50,7 @@ def bind_ioresult( ... )(...) == IOSuccess(2) """ + @kinded def factory( container: KindN[ @@ -58,4 +61,5 @@ def factory( ], ) -> KindN[_IOResultLikeKind, _UpdatedType, _SecondType, _ThirdType]: return container.bind_ioresult(function) + return factory diff --git a/returns/pointfree/bind_optional.py b/returns/pointfree/bind_optional.py index e35af8dee..ab54a3c54 100644 --- a/returns/pointfree/bind_optional.py +++ b/returns/pointfree/bind_optional.py @@ -14,10 +14,12 @@ def bind_optional( function: Callable[[_FirstType], _UpdatedType | None], -) -> Kinded[Callable[ - [KindN[_MaybeLikeKind, _FirstType, _SecondType, _ThirdType]], - KindN[_MaybeLikeKind, _UpdatedType, _SecondType, _ThirdType], -]]: +) -> Kinded[ + Callable[ + [KindN[_MaybeLikeKind, _FirstType, _SecondType, _ThirdType]], + KindN[_MaybeLikeKind, _UpdatedType, _SecondType, _ThirdType], + ] +]: """ Binds a function returning optional value over a container. @@ -46,9 +48,11 @@ def bind_optional( for more info. """ + @kinded def factory( container: KindN[_MaybeLikeKind, _FirstType, _SecondType, _ThirdType], ) -> KindN[_MaybeLikeKind, _UpdatedType, _SecondType, _ThirdType]: return container.bind_optional(function) + return factory diff --git a/returns/pointfree/bind_result.py b/returns/pointfree/bind_result.py index 28ee180a2..99d099834 100644 --- a/returns/pointfree/bind_result.py +++ b/returns/pointfree/bind_result.py @@ -19,10 +19,12 @@ def bind_result( function: Callable[[_FirstType], Result[_UpdatedType, _SecondType]], -) -> Kinded[Callable[ - [KindN[_ResultLikeKind, _FirstType, _SecondType, _ThirdType]], - KindN[_ResultLikeKind, _UpdatedType, _SecondType, _ThirdType], -]]: +) -> Kinded[ + Callable[ + [KindN[_ResultLikeKind, _FirstType, _SecondType, _ThirdType]], + KindN[_ResultLikeKind, _UpdatedType, _SecondType, _ThirdType], + ] +]: """ Composes successful container with a function that returns a container. @@ -47,9 +49,11 @@ def bind_result( >>> assert bound(RequiresContextResult.from_value(1))(...) == Success(2) """ + @kinded def factory( container: KindN[_ResultLikeKind, _FirstType, _SecondType, _ThirdType], ) -> KindN[_ResultLikeKind, _UpdatedType, _SecondType, _ThirdType]: return container.bind_result(function) + return factory diff --git a/returns/pointfree/compose_result.py b/returns/pointfree/compose_result.py index 7b2e3035e..4c72b8b1f 100644 --- a/returns/pointfree/compose_result.py +++ b/returns/pointfree/compose_result.py @@ -18,10 +18,12 @@ def compose_result( [Result[_FirstType, _SecondType]], Kind3[_IOResultLikeKind, _NewFirstType, _SecondType, _ThirdType], ], -) -> Kinded[Callable[ - [Kind3[_IOResultLikeKind, _FirstType, _SecondType, _ThirdType]], - Kind3[_IOResultLikeKind, _NewFirstType, _SecondType, _ThirdType], -]]: +) -> Kinded[ + Callable[ + [Kind3[_IOResultLikeKind, _FirstType, _SecondType, _ThirdType]], + Kind3[_IOResultLikeKind, _NewFirstType, _SecondType, _ThirdType], + ] +]: """ Composes inner ``Result`` with ``IOResultLike`` returning function. @@ -46,11 +48,16 @@ def compose_result( ... ) == IOFailure('failure') """ + @kinded def factory( container: Kind3[ - _IOResultLikeKind, _FirstType, _SecondType, _ThirdType, + _IOResultLikeKind, + _FirstType, + _SecondType, + _ThirdType, ], ) -> Kind3[_IOResultLikeKind, _NewFirstType, _SecondType, _ThirdType]: return container.compose_result(function) + return factory diff --git a/returns/pointfree/cond.py b/returns/pointfree/cond.py index 07649ebbc..1d71e7221 100644 --- a/returns/pointfree/cond.py +++ b/returns/pointfree/cond.py @@ -19,10 +19,10 @@ def cond( success_value: _ValueType, ) -> Kinded[ Callable[ - [bool], KindN[_SingleFailableKind, _ValueType, _ErrorType, NoDeps], + [bool], + KindN[_SingleFailableKind, _ValueType, _ErrorType, NoDeps], ] -]: - """Reduce the boilerplate when choosing paths with ``SingleFailableN``.""" +]: ... @overload @@ -32,16 +32,14 @@ def cond( error_value: _ErrorType, ) -> Kinded[ Callable[ - [bool], KindN[_DiverseFailableKind, _ValueType, _ErrorType, NoDeps], + [bool], + KindN[_DiverseFailableKind, _ValueType, _ErrorType, NoDeps], ] -]: - """Reduce the boilerplate when choosing paths with ``DiverseFailableN``.""" +]: ... def cond( - container_type: ( - type[_SingleFailableKind] | type[_DiverseFailableKind] - ), + container_type: (type[_SingleFailableKind] | type[_DiverseFailableKind]), success_value: _ValueType, error_value: _ErrorType | None = None, ): @@ -71,8 +69,13 @@ def cond( >>> assert cond(Maybe, 10.0)(False) == Nothing """ - def factory(is_success: bool): + + def factory(is_success: bool): # noqa: FBT001 return internal_cond( - container_type, is_success, success_value, error_value, + container_type, + is_success, + success_value, + error_value, ) + return factory diff --git a/returns/pointfree/lash.py b/returns/pointfree/lash.py index 16b63e2c2..0f97e0675 100644 --- a/returns/pointfree/lash.py +++ b/returns/pointfree/lash.py @@ -17,10 +17,12 @@ def lash( [_SecondType], KindN[_LashableKind, _FirstType, _UpdatedType, _ThirdType], ], -) -> Kinded[Callable[ - [KindN[_LashableKind, _FirstType, _SecondType, _ThirdType]], - KindN[_LashableKind, _FirstType, _UpdatedType, _ThirdType], -]]: +) -> Kinded[ + Callable[ + [KindN[_LashableKind, _FirstType, _SecondType, _ThirdType]], + KindN[_LashableKind, _FirstType, _UpdatedType, _ThirdType], + ] +]: """ Turns function's input parameter from a regular value to a container. @@ -49,9 +51,11 @@ def lash( See :class:`returns.interfaces.lashable.Lashable` for more info. """ + @kinded def factory( container: KindN[_LashableKind, _FirstType, _SecondType, _ThirdType], ) -> KindN[_LashableKind, _FirstType, _UpdatedType, _ThirdType]: return container.lash(function) + return factory diff --git a/returns/pointfree/map.py b/returns/pointfree/map.py index bd83af8ad..6fe264bc8 100644 --- a/returns/pointfree/map.py +++ b/returns/pointfree/map.py @@ -14,10 +14,12 @@ def map_( function: Callable[[_FirstType], _UpdatedType], -) -> Kinded[Callable[ - [KindN[_MappableKind, _FirstType, _SecondType, _ThirdType]], - KindN[_MappableKind, _UpdatedType, _SecondType, _ThirdType], -]]: +) -> Kinded[ + Callable[ + [KindN[_MappableKind, _FirstType, _SecondType, _ThirdType]], + KindN[_MappableKind, _UpdatedType, _SecondType, _ThirdType], + ] +]: """ Lifts function to be wrapped in a container for better composition. @@ -45,9 +47,11 @@ def map_( - https://wiki.haskell.org/Lifting """ + @kinded def factory( container: KindN[_MappableKind, _FirstType, _SecondType, _ThirdType], ) -> KindN[_MappableKind, _UpdatedType, _SecondType, _ThirdType]: return container.map(function) + return factory diff --git a/returns/pointfree/modify_env.py b/returns/pointfree/modify_env.py index 2663cadde..04a9cb190 100644 --- a/returns/pointfree/modify_env.py +++ b/returns/pointfree/modify_env.py @@ -15,10 +15,12 @@ def modify_env2( function: Callable[[_UpdatedType], _SecondType], -) -> Kinded[Callable[ - [Kind2[_Reader2Kind, _FirstType, _SecondType]], - Kind2[_Reader2Kind, _FirstType, _UpdatedType], -]]: +) -> Kinded[ + Callable[ + [Kind2[_Reader2Kind, _FirstType, _SecondType]], + Kind2[_Reader2Kind, _FirstType, _UpdatedType], + ] +]: """ Modifies the second type argument of a ``ReaderLike2``. @@ -44,20 +46,24 @@ def modify_env2( for more info. """ + @kinded def factory( container: Kind2[_Reader2Kind, _FirstType, _SecondType], ) -> Kind2[_Reader2Kind, _FirstType, _UpdatedType]: return container.modify_env(function) + return factory def modify_env3( function: Callable[[_UpdatedType], _ThirdType], -) -> Kinded[Callable[ - [Kind3[_Reader3Kind, _FirstType, _SecondType, _ThirdType]], - Kind3[_Reader3Kind, _FirstType, _SecondType, _UpdatedType], -]]: +) -> Kinded[ + Callable[ + [Kind3[_Reader3Kind, _FirstType, _SecondType, _ThirdType]], + Kind3[_Reader3Kind, _FirstType, _SecondType, _UpdatedType], + ] +]: """ Modifies the third type argument of a ``ReaderLike3``. @@ -83,11 +89,13 @@ def modify_env3( for more info. """ + @kinded def factory( container: Kind3[_Reader3Kind, _FirstType, _SecondType, _ThirdType], ) -> Kind3[_Reader3Kind, _FirstType, _SecondType, _UpdatedType]: return container.modify_env(function) + return factory diff --git a/returns/pointfree/unify.py b/returns/pointfree/unify.py index 53071462e..fd79f4c2f 100644 --- a/returns/pointfree/unify.py +++ b/returns/pointfree/unify.py @@ -18,7 +18,10 @@ def unify( # noqa: WPS234 function: Callable[ [_FirstType], KindN[ - _DiverseFailableKind, _NewFirstType, _NewSecondType, _NewThirdType, + _DiverseFailableKind, + _NewFirstType, + _NewSecondType, + _NewThirdType, ], ], ) -> Kinded[ @@ -56,10 +59,14 @@ def unify( # noqa: WPS234 >>> assert unify(bindable)(Failure(42)) == Failure(42) """ + @kinded def factory( container: KindN[ - _DiverseFailableKind, _FirstType, _SecondType, _ThirdType, + _DiverseFailableKind, + _FirstType, + _SecondType, + _ThirdType, ], ) -> KindN[ _DiverseFailableKind, @@ -68,4 +75,5 @@ def factory( _NewThirdType, ]: return container.bind(function) # type: ignore + return factory diff --git a/returns/primitives/asserts.py b/returns/primitives/asserts.py index dfc3cd21b..cf03c7f2f 100644 --- a/returns/primitives/asserts.py +++ b/returns/primitives/asserts.py @@ -24,24 +24,28 @@ def assert_equal( By the way, ``anyio`` should be installed separately. """ assert _convert( - first, deps=deps, backend=backend, + first, + deps=deps, + backend=backend, ) == _convert( - second, deps=deps, backend=backend, - ), '{0} == {1}'.format(first, second) + second, + deps=deps, + backend=backend, + ), f'{first} == {second}' def _convert(container, *, deps, backend: str): - from returns.interfaces.specific import future, reader + from returns.interfaces.specific import future, reader # noqa: PLC0415 if isinstance(container, future.AwaitableFutureN): - import anyio + import anyio # noqa: PLC0415 return _convert( anyio.run(container.awaitable, backend=backend), deps=deps, backend=backend, ) - elif isinstance(container, reader.Contextable): + if isinstance(container, reader.Contextable): return _convert( container(deps), deps=deps, diff --git a/returns/primitives/container.py b/returns/primitives/container.py index d7be94281..a95568aec 100644 --- a/returns/primitives/container.py +++ b/returns/primitives/container.py @@ -1,4 +1,4 @@ -from abc import ABCMeta +from abc import ABC from typing import Any, TypeVar from typing_extensions import TypedDict @@ -23,7 +23,7 @@ class _PickleState(TypedDict): container_value: Any -class BaseContainer(Immutable, metaclass=ABCMeta): +class BaseContainer(Immutable, ABC): """Utility class to provide all needed magic methods to the context.""" __slots__ = ('_inner_value',) @@ -35,16 +35,16 @@ def __init__(self, inner_value) -> None: 'value' is any arbitrary value of any type including functions. """ - object.__setattr__(self, '_inner_value', inner_value) # noqa: WPS609 + object.__setattr__(self, '_inner_value', inner_value) def __repr__(self) -> str: """Used to display details of object.""" - return '<{0}: {1}>'.format( + return '<{}: {}>'.format( self.__class__.__qualname__.strip('_'), str(self._inner_value), ) - def __eq__(self, other: Any) -> bool: + def __eq__(self, other: object) -> bool: """Used to compare two 'Container' objects.""" return container_equality(self, other) # type: ignore @@ -59,12 +59,14 @@ def __getstate__(self) -> _PickleState: def __setstate__(self, state: _PickleState | Any) -> None: """Loading state from pickled data.""" if isinstance(state, dict) and 'container_value' in state: - object.__setattr__( # noqa: WPS609 - self, '_inner_value', state['container_value'], + object.__setattr__( + self, + '_inner_value', + state['container_value'], ) else: # backward compatibility with 0.19.0 and earlier - object.__setattr__(self, '_inner_value', state) # noqa: WPS609 + object.__setattr__(self, '_inner_value', state) def container_equality( @@ -79,5 +81,5 @@ def container_equality( if type(self) != type(other): # noqa: WPS516, E721 return False return bool( - self._inner_value == other._inner_value, # type: ignore # noqa: WPS437 + self._inner_value == other._inner_value, # type: ignore # noqa: SLF001 ) diff --git a/returns/primitives/hkt.py b/returns/primitives/hkt.py index b374a8a53..7387d316c 100644 --- a/returns/primitives/hkt.py +++ b/returns/primitives/hkt.py @@ -3,13 +3,13 @@ from typing_extensions import Never, TypeVarTuple, Unpack -_InstanceType = TypeVar('_InstanceType', covariant=True) -_TypeArgType1 = TypeVar('_TypeArgType1', covariant=True) -_TypeArgType2 = TypeVar('_TypeArgType2', covariant=True) -_TypeArgType3 = TypeVar('_TypeArgType3', covariant=True) +_InstanceType_co = TypeVar('_InstanceType_co', covariant=True) +_TypeArgType1_co = TypeVar('_TypeArgType1_co', covariant=True) +_TypeArgType2_co = TypeVar('_TypeArgType2_co', covariant=True) +_TypeArgType3_co = TypeVar('_TypeArgType3_co', covariant=True) -_FunctionDefType = TypeVar( - '_FunctionDefType', +_FunctionDefType_co = TypeVar( + '_FunctionDefType_co', bound=Callable, covariant=True, # This is a must! Otherwise it would not work. ) @@ -19,14 +19,10 @@ ) _UpdatedType = TypeVar('_UpdatedType') - -_FirstKind = TypeVar('_FirstKind') -_SecondKind = TypeVar('_SecondKind') - _TypeVars = TypeVarTuple('_TypeVars') -class KindN(Generic[_InstanceType, Unpack[_TypeVars]]): +class KindN(Generic[_InstanceType_co, Unpack[_TypeVars]]): """ Emulation support for Higher Kinded Types. @@ -77,7 +73,7 @@ def impossible(generic: T, value: V) -> T[V]: a possible metaclass conflict with other metaclasses. Current API allows you to mix ``KindN`` anywhere. - We allow ``_InstanceType`` of ``KindN`` + We allow ``_InstanceType_co`` of ``KindN`` to be ``Instance`` type or ``TypeVarType`` with ``bound=...``. See also: @@ -91,6 +87,7 @@ def impossible(generic: T, value: V) -> T[V]: __slots__ = () if TYPE_CHECKING: # noqa: WPS604 # pragma: no cover + def __getattr__(self, attrname: str): """ This function is required for ``get_attribute_hook`` in mypy plugin. @@ -101,16 +98,18 @@ def __getattr__(self, attrname: str): #: Type alias for kinds with one type argument. -Kind1 = KindN[_InstanceType, _TypeArgType1, Any, Any] +Kind1 = KindN[_InstanceType_co, _TypeArgType1_co, Any, Any] #: Type alias for kinds with two type arguments. -Kind2 = KindN[_InstanceType, _TypeArgType1, _TypeArgType2, Any] +Kind2 = KindN[_InstanceType_co, _TypeArgType1_co, _TypeArgType2_co, Any] #: Type alias for kinds with three type arguments. -Kind3 = KindN[_InstanceType, _TypeArgType1, _TypeArgType2, _TypeArgType3] +Kind3 = KindN[ + _InstanceType_co, _TypeArgType1_co, _TypeArgType2_co, _TypeArgType3_co +] -class SupportsKindN(KindN[_InstanceType, Unpack[_TypeVars]]): +class SupportsKindN(KindN[_InstanceType_co, Unpack[_TypeVars]]): """ Base class for your containers. @@ -132,23 +131,34 @@ class SupportsKindN(KindN[_InstanceType, Unpack[_TypeVars]]): #: Type alias used for inheritance with one type argument. SupportsKind1 = SupportsKindN[ - _InstanceType, _TypeArgType1, Never, Never, + _InstanceType_co, + _TypeArgType1_co, + Never, + Never, ] #: Type alias used for inheritance with two type arguments. SupportsKind2 = SupportsKindN[ - _InstanceType, _TypeArgType1, _TypeArgType2, Never, + _InstanceType_co, + _TypeArgType1_co, + _TypeArgType2_co, + Never, ] #: Type alias used for inheritance with three type arguments. SupportsKind3 = SupportsKindN[ - _InstanceType, _TypeArgType1, _TypeArgType2, _TypeArgType3, + _InstanceType_co, + _TypeArgType1_co, + _TypeArgType2_co, + _TypeArgType3_co, ] def dekind( - kind: KindN[_InstanceType, _TypeArgType1, _TypeArgType2, _TypeArgType3], -) -> _InstanceType: + kind: KindN[ + _InstanceType_co, _TypeArgType1_co, _TypeArgType2_co, _TypeArgType3_co + ], +) -> _InstanceType_co: """ Turns ``Kind1[IO, int]`` type into real ``IO[int]`` type. @@ -179,6 +189,7 @@ def dekind( # 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` @@ -187,7 +198,7 @@ def dekind( # 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 +class Kinded(Protocol[_FunctionDefType_co]): # type: ignore """ Protocol that tracks kinded functions calls. @@ -198,7 +209,7 @@ class Kinded(Protocol[_FunctionDefType]): # type: ignore __slots__ = () #: Used to translate `KindN` into real types. - __call__: _FunctionDefType + __call__: _FunctionDefType_co def __get__( self, diff --git a/returns/primitives/laws.py b/returns/primitives/laws.py index 309fb811c..c08b4117b 100644 --- a/returns/primitives/laws.py +++ b/returns/primitives/laws.py @@ -21,14 +21,14 @@ class Law(Immutable): Use ``Law1``, ``Law2`` or ``Law3`` instead. """ - __slots__ = ('definition', ) + __slots__ = ('definition',) #: Function used to define this law. definition: Callable def __init__(self, function) -> None: """Saves function to the inner state.""" - object.__setattr__(self, 'definition', function) # noqa: WPS609 + object.__setattr__(self, 'definition', function) @final @property @@ -126,16 +126,13 @@ def laws(cls) -> dict[type['Lawful'], Sequence[Law]]: # noqa: WPS210 """ seen = { - '{0}.{1}'.format( - parent.__module__, # noqa: WPS609 - parent.__qualname__, - ): parent + f'{parent.__module__}.{parent.__qualname__}': parent for parent in cls.__mro__ } laws = {} for klass in seen.values(): - current_laws = klass.__dict__.get('_laws', ()) # noqa: WPS609 + current_laws = klass.__dict__.get('_laws', ()) if not current_laws: continue laws[klass] = current_laws diff --git a/returns/primitives/reawaitable.py b/returns/primitives/reawaitable.py index d8f5e460c..fba8505d3 100644 --- a/returns/primitives/reawaitable.py +++ b/returns/primitives/reawaitable.py @@ -46,7 +46,7 @@ class ReAwaitable: """ - __slots__ = ('_coro', '_cache') + __slots__ = ('_cache', '_coro') def __init__(self, coro: Awaitable[_ValueType]) -> None: """We need just an awaitable to work with.""" @@ -77,7 +77,7 @@ def __await__(self) -> Generator[None, None, _ValueType]: Hello """ - return self._awaitable().__await__() # noqa: WPS609 + return self._awaitable().__await__() def __repr__(self) -> str: """ diff --git a/returns/primitives/tracing.py b/returns/primitives/tracing.py index 6f73d40f3..4354e7d17 100644 --- a/returns/primitives/tracing.py +++ b/returns/primitives/tracing.py @@ -1,8 +1,8 @@ import types from collections.abc import Callable, Iterator -from contextlib import contextmanager +from contextlib import AbstractContextManager, contextmanager from inspect import FrameInfo, stack -from typing import ContextManager, TypeVar, overload +from typing import TypeVar, overload from returns.result import Failure @@ -10,18 +10,16 @@ @overload -def collect_traces() -> ContextManager[None]: - """Context Manager to active traces collect to the Failures.""" +def collect_traces() -> AbstractContextManager[None]: ... @overload -def collect_traces(function: _FunctionType) -> _FunctionType: - """Decorator to active traces collect to the Failures.""" +def collect_traces(function: _FunctionType) -> _FunctionType: ... def collect_traces( function: _FunctionType | None = None, -) -> _FunctionType | ContextManager[None]: # noqa: DAR101, DAR201, DAR301 +) -> _FunctionType | AbstractContextManager[None]: """ Context Manager/Decorator to active traces collect to the Failures. @@ -39,7 +37,10 @@ def collect_traces( >>> assert non_traced_failure.trace is None >>> assert isinstance(traced_failure.trace, list) - >>> assert all(isinstance(trace_line, FrameInfo) for trace_line in traced_failure.trace) + >>> assert all( + ... isinstance(trace_line, FrameInfo) + ... for trace_line in traced_failure.trace + ... ) >>> for trace_line in traced_failure.trace: ... print( # doctest: +SKIP @@ -56,6 +57,7 @@ def collect_traces( # doctest: # noqa: DAR301, E501 """ + @contextmanager def factory() -> Iterator[None]: unpatched_get_trace = getattr(Failure, '_get_trace') # noqa: B009 @@ -65,6 +67,7 @@ def factory() -> Iterator[None]: yield finally: setattr(Failure, '_get_trace', unpatched_get_trace) # noqa: B010 + return factory()(function) if function else factory() diff --git a/returns/primitives/types.py b/returns/primitives/types.py index a28e40d1c..0cb15b7d8 100644 --- a/returns/primitives/types.py +++ b/returns/primitives/types.py @@ -27,7 +27,7 @@ class Immutable: See :class:`returns.primitives.container.BaseContainer` for examples. - """ # noqa: RST307 + """ __slots__ = () @@ -41,8 +41,8 @@ def __deepcopy__(self, memo: dict[Any, Any]) -> Self: def __setattr__(self, attr_name: str, attr_value: Any) -> Never: """Makes inner state of the containers immutable for modification.""" - raise ImmutableStateError() + raise ImmutableStateError def __delattr__(self, attr_name: str) -> Never: # noqa: WPS603 """Makes inner state of the containers immutable for deletion.""" - raise ImmutableStateError() + raise ImmutableStateError diff --git a/returns/result.py b/returns/result.py index 293ede7e4..7ca217d2a 100644 --- a/returns/result.py +++ b/returns/result.py @@ -1,4 +1,4 @@ -from abc import ABCMeta +from abc import ABC from collections.abc import Callable, Generator, Iterator from functools import wraps from inspect import FrameInfo @@ -12,9 +12,9 @@ from returns.primitives.hkt import Kind2, SupportsKind2 # Definitions: -_ValueType = TypeVar('_ValueType', covariant=True) +_ValueType_co = TypeVar('_ValueType_co', covariant=True) _NewValueType = TypeVar('_NewValueType') -_ErrorType = TypeVar('_ErrorType', covariant=True) +_ErrorType_co = TypeVar('_ErrorType_co', covariant=True) _NewErrorType = TypeVar('_NewErrorType') _FirstType = TypeVar('_FirstType') @@ -23,9 +23,9 @@ class Result( # type: ignore[type-var] BaseContainer, - SupportsKind2['Result', _ValueType, _ErrorType], - result.ResultBased2[_ValueType, _ErrorType], - metaclass=ABCMeta, + SupportsKind2['Result', _ValueType_co, _ErrorType_co], + result.ResultBased2[_ValueType_co, _ErrorType_co], + ABC, ): """ Base class for :class:`~Failure` and :class:`~Success`. @@ -42,7 +42,7 @@ class Result( # type: ignore[type-var] __slots__ = ('_trace',) __match_args__ = ('_inner_value',) - _inner_value: _ValueType | _ErrorType + _inner_value: _ValueType_co | _ErrorType_co _trace: list[FrameInfo] | None #: Typesafe equality comparison with other `Result` objects. @@ -53,7 +53,7 @@ def trace(self) -> list[FrameInfo] | None: """Returns a list with stack trace when :func:`~Failure` was called.""" return self._trace - def swap(self) -> 'Result[_ErrorType, _ValueType]': + def swap(self) -> 'Result[_ErrorType_co, _ValueType_co]': """ Swaps value and error types. @@ -72,8 +72,8 @@ def swap(self) -> 'Result[_ErrorType, _ValueType]': def map( self, - function: Callable[[_ValueType], _NewValueType], - ) -> 'Result[_NewValueType, _ErrorType]': + function: Callable[[_ValueType_co], _NewValueType], + ) -> 'Result[_NewValueType, _ErrorType_co]': """ Composes successful container with a pure function. @@ -93,10 +93,10 @@ def apply( self, container: Kind2[ 'Result', - Callable[[_ValueType], _NewValueType], - _ErrorType, + Callable[[_ValueType_co], _NewValueType], + _ErrorType_co, ], - ) -> 'Result[_NewValueType, _ErrorType]': + ) -> 'Result[_NewValueType, _ErrorType_co]': """ Calls a wrapped function in a container on this container. @@ -118,10 +118,10 @@ def apply( def bind( self, function: Callable[ - [_ValueType], - Kind2['Result', _NewValueType, _ErrorType], + [_ValueType_co], + Kind2['Result', _NewValueType, _ErrorType_co], ], - ) -> 'Result[_NewValueType, _ErrorType]': + ) -> 'Result[_NewValueType, _ErrorType_co]': """ Composes successful container with a function that returns a container. @@ -145,8 +145,8 @@ def bind( def alt( self, - function: Callable[[_ErrorType], _NewErrorType], - ) -> 'Result[_ValueType, _NewErrorType]': + function: Callable[[_ErrorType_co], _NewErrorType], + ) -> 'Result[_ValueType_co, _NewErrorType]': """ Composes failed container with a pure function to modify failure. @@ -165,9 +165,10 @@ def alt( def lash( self, function: Callable[ - [_ErrorType], Kind2['Result', _ValueType, _NewErrorType], + [_ErrorType_co], + Kind2['Result', _ValueType_co, _NewErrorType], ], - ) -> 'Result[_ValueType, _NewErrorType]': + ) -> 'Result[_ValueType_co, _NewErrorType]': """ Composes failed container with a function that returns a container. @@ -186,7 +187,7 @@ def lash( """ - def __iter__(self) -> Iterator[_ValueType]: + def __iter__(self) -> Iterator[_ValueType_co]: """API for :ref:`do-notation`.""" yield self.unwrap() @@ -226,7 +227,7 @@ def do( def value_or( self, default_value: _NewValueType, - ) -> _ValueType | _NewValueType: + ) -> _ValueType_co | _NewValueType: """ Get value or default value. @@ -238,7 +239,7 @@ def value_or( """ - def unwrap(self) -> _ValueType: + def unwrap(self) -> _ValueType_co: """ Get value or raise exception. @@ -253,9 +254,9 @@ def unwrap(self) -> _ValueType: ... returns.primitives.exceptions.UnwrapFailedError - """ # noqa: RST307 + """ - def failure(self) -> _ErrorType: + def failure(self) -> _ErrorType_co: """ Get failed value or raise exception. @@ -270,11 +271,12 @@ def failure(self) -> _ErrorType: ... returns.primitives.exceptions.UnwrapFailedError - """ # noqa: RST307 + """ @classmethod def from_value( - cls, inner_value: _NewValueType, + cls, + inner_value: _NewValueType, ) -> 'Result[_NewValueType, Any]': """ One more value to create success unit values. @@ -294,7 +296,8 @@ def from_value( @classmethod def from_failure( - cls, inner_value: _NewErrorType, + cls, + inner_value: _NewErrorType, ) -> 'Result[Any, _NewErrorType]': """ One more value to create failure unit values. @@ -314,7 +317,8 @@ def from_failure( @classmethod def from_result( - cls, inner_value: 'Result[_NewValueType, _NewErrorType]', + cls, + inner_value: 'Result[_NewValueType, _NewErrorType]', ) -> 'Result[_NewValueType, _NewErrorType]': """ Creates a new ``Result`` instance from existing ``Result`` instance. @@ -332,7 +336,7 @@ def from_result( @final # noqa: WPS338 -class Failure(Result[Any, _ErrorType]): # noqa: WPS338 +class Failure(Result[Any, _ErrorType_co]): # noqa: WPS338 """ Represents a calculation which has failed. @@ -341,14 +345,15 @@ class Failure(Result[Any, _ErrorType]): # noqa: WPS338 __slots__ = () - _inner_value: _ErrorType + _inner_value: _ErrorType_co - def __init__(self, inner_value: _ErrorType) -> None: + def __init__(self, inner_value: _ErrorType_co) -> None: """Failure constructor.""" super().__init__(inner_value) - object.__setattr__(self, '_trace', self._get_trace()) # noqa: WPS609 + object.__setattr__(self, '_trace', self._get_trace()) + + if not TYPE_CHECKING: # noqa: WPS604 # pragma: no branch - if not TYPE_CHECKING: # noqa: C901, WPS604 # pragma: no branch def alt(self, function): """Composes failed container with a pure function to modify failure.""" # noqa: E501 return Failure(function(self._inner_value)) @@ -386,7 +391,7 @@ def unwrap(self) -> Never: raise UnwrapFailedError(self) from self._inner_value raise UnwrapFailedError(self) - def failure(self) -> _ErrorType: + def failure(self) -> _ErrorType_co: """Returns failed value.""" return self._inner_value @@ -395,7 +400,7 @@ def _get_trace(self) -> list[FrameInfo] | None: @final -class Success(Result[_ValueType, Any]): +class Success(Result[_ValueType_co, Any]): """ Represents a calculation which has succeeded and contains the result. @@ -404,13 +409,14 @@ class Success(Result[_ValueType, Any]): __slots__ = () - _inner_value: _ValueType + _inner_value: _ValueType_co - def __init__(self, inner_value: _ValueType) -> None: + def __init__(self, inner_value: _ValueType_co) -> None: """Success constructor.""" super().__init__(inner_value) - if not TYPE_CHECKING: # noqa: C901, WPS604 # pragma: no branch + if not TYPE_CHECKING: # noqa: WPS604 # pragma: no branch + def alt(self, function): """Does nothing for ``Success``.""" return self @@ -444,7 +450,7 @@ def swap(self): """Successes swap to :class:`Failure`.""" return Failure(self._inner_value) - def unwrap(self) -> _ValueType: + def unwrap(self) -> _ValueType_co: """Returns the unwrapped value from successful container.""" return self._inner_value @@ -455,8 +461,8 @@ def failure(self) -> Never: # Aliases: -#: Alias for ``Result[_ValueType, Exception]``. -ResultE: TypeAlias = Result[_ValueType, Exception] +#: Alias for ``Result[_ValueType_co, Exception]``. +ResultE: TypeAlias = Result[_ValueType_co, Exception] # Decorators: @@ -466,32 +472,29 @@ def failure(self) -> Never: @overload def safe( - function: Callable[_FuncParams, _ValueType], + function: Callable[_FuncParams, _ValueType_co], /, -) -> Callable[_FuncParams, ResultE[_ValueType]]: - """Decorator to convert exception-throwing for any kind of Exception.""" +) -> Callable[_FuncParams, ResultE[_ValueType_co]]: ... @overload def safe( exceptions: tuple[type[_ExceptionType], ...], ) -> Callable[ - [Callable[_FuncParams, _ValueType]], - Callable[_FuncParams, Result[_ValueType, _ExceptionType]], -]: - """Decorator to convert exception-throwing just for a set of Exceptions.""" + [Callable[_FuncParams, _ValueType_co]], + Callable[_FuncParams, Result[_ValueType_co, _ExceptionType]], +]: ... -def safe( # noqa: WPS234, C901 +def safe( # noqa: WPS234 exceptions: ( - Callable[_FuncParams, _ValueType] | - tuple[type[_ExceptionType], ...] + Callable[_FuncParams, _ValueType_co] | tuple[type[_ExceptionType], ...] ), ) -> ( - Callable[_FuncParams, ResultE[_ValueType]] | - Callable[ - [Callable[_FuncParams, _ValueType]], - Callable[_FuncParams, Result[_ValueType, _ExceptionType]], + Callable[_FuncParams, ResultE[_ValueType_co]] + | Callable[ + [Callable[_FuncParams, _ValueType_co]], + Callable[_FuncParams, Result[_ValueType_co, _ExceptionType]], ] ): """ @@ -534,19 +537,21 @@ def safe( # noqa: WPS234, C901 Similar to :func:`returns.io.impure_safe` and :func:`returns.future.future_safe` decorators. """ + def factory( - inner_function: Callable[_FuncParams, _ValueType], + inner_function: Callable[_FuncParams, _ValueType_co], inner_exceptions: tuple[type[_ExceptionType], ...], - ) -> Callable[_FuncParams, Result[_ValueType, _ExceptionType]]: + ) -> Callable[_FuncParams, Result[_ValueType_co, _ExceptionType]]: @wraps(inner_function) def decorator( *args: _FuncParams.args, **kwargs: _FuncParams.kwargs, - ) -> Result[_ValueType, _ExceptionType]: + ) -> Result[_ValueType_co, _ExceptionType]: try: return Success(inner_function(*args, **kwargs)) except inner_exceptions as exc: return Failure(exc) + return decorator if isinstance(exceptions, tuple): @@ -582,6 +587,7 @@ def attempt( >>> assert parse_json('incorrect input') == Failure('incorrect input') """ + @wraps(func) def decorator(arg: _FirstType) -> Result[_NewValueType, _FirstType]: try: diff --git a/returns/trampolines.py b/returns/trampolines.py index b0dbc0e48..b446e63b3 100644 --- a/returns/trampolines.py +++ b/returns/trampolines.py @@ -16,7 +16,7 @@ class Trampoline(Generic[_ReturnType]): Primitive to convert recursion into an actual object. """ - __slots__ = ('func', 'args', 'kwargs') + __slots__ = ('args', 'func', 'kwargs') def __init__( # noqa: WPS451 self, @@ -91,5 +91,5 @@ def decorator( trampoline_result = trampoline_result() return trampoline_result - decorator._orig_func = func # type: ignore[attr-defined] # noqa: WPS437 + decorator._orig_func = func # type: ignore[attr-defined] # noqa: SLF001 return decorator diff --git a/returns/unsafe.py b/returns/unsafe.py index 2c8080067..454f0e0f4 100644 --- a/returns/unsafe.py +++ b/returns/unsafe.py @@ -28,4 +28,4 @@ def unsafe_perform_io(wrapped_in_io: IO[_ValueType]) -> _ValueType: - https://github.com/seddonym/import-linter """ - return wrapped_in_io._inner_value # noqa: WPS437 + return wrapped_in_io._inner_value # noqa: SLF001 diff --git a/setup.cfg b/setup.cfg index 2ce466c3d..7c9cd4987 100644 --- a/setup.cfg +++ b/setup.cfg @@ -9,23 +9,12 @@ show-source = true doctests = true statistics = false -# darglint configuration: -# https://github.com/terrencepreilly/darglint -strictness = long -docstring-style = numpy - -# Plugins: -max-complexity = 6 -max-line-length = 80 -staticmethod-decorators = - staticmethod - law_definition - # wemake-python-styleguide -max-annotation-complexity = 4 -i-control-code = false +max-annotation-complexity = 5 allowed-domain-names = some, result, do +select = WPS, E999 + extend-exclude = .venv build @@ -34,12 +23,6 @@ extend-exclude = experiments ignore = - D100, - D104, - D401, - W504, - X100, - Y021, WPS113, WPS201, WPS202, @@ -47,15 +30,12 @@ ignore = WPS215, WPS235, WPS320, + WPS412, WPS433, WPS436, WPS440, WPS450, WPS612, - RST303, - RST304, - DAR103, - DAR203, per-file-ignores = # We allow reexport: @@ -72,13 +52,13 @@ per-file-ignores = # Some rules cannot be applied to context: returns/context/*.py: WPS201, WPS204, WPS226, WPS326, WPS430 # We allow `futures` to do attribute access: - returns/future.py: WPS437 + returns/future.py: WPS402 returns/_internal/futures/*.py: WPS204, WPS433, WPS437 # We allow a lot of durty hacks in our plugins: returns/contrib/mypy/*.py: S101, WPS201 returns/contrib/pytest/__init__.py: F401 - returns/contrib/pytest/plugin.py: WPS201, WPS430, WPS437, WPS609 - returns/contrib/hypothesis/*.py: WPS437, WPS609 + returns/contrib/pytest/plugin.py: WPS201, WPS402, WPS430, WPS437 + returns/contrib/hypothesis/*.py: WPS437 # TODO: remove after mypy@0.800 returns/contrib/mypy/_typeops/visitor.py: S101, WPS232 # Allow class attributes literals for slots and setattr: @@ -141,12 +121,8 @@ omit = # Hypothesis is also excluded: returns/contrib/hypothesis/* -[coverage:report] -exclude_lines = - # a more strict default pragma - \# pragma: no cover\b - - ^if TYPE_CHECKING: +plugins = + covdefaults [mypy] 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 6586be299..57bf4a07f 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 @@ -1,12 +1,12 @@ -from returns.context import RequiresContext +from returns.context import RequiresContext, RequiresContextResult from returns.context import RequiresContextIOResult as RCR # noqa: N814 -from returns.context import RequiresContextResult from returns.io import IOFailure, IOResult, IOSuccess from returns.result import Failure, Result, Success def test_bind(): """Ensures that bind works.""" + def factory(inner_value: int) -> RCR[float, str, int]: if inner_value > 0: return RCR(lambda deps: IOSuccess(inner_value / deps)) @@ -17,13 +17,18 @@ def factory(inner_value: int) -> RCR[float, str, int]: assert bound.bind(factory)(2) == factory(input_value)(2) assert bound.bind(factory)(2) == IOSuccess(2.5) - assert RCR.from_value(0).bind( - factory, - )(2) == factory(0)(2) == IOFailure('0') + assert ( + RCR.from_value(0).bind( + factory, + )(2) + == factory(0)(2) + == IOFailure('0') + ) def test_bind_regular_result(): """Ensures that regular ``Result`` can be bound.""" + def factory(inner_value: int) -> Result[int, str]: if inner_value > 0: return Success(inner_value + 1) @@ -41,6 +46,7 @@ def factory(inner_value: int) -> Result[int, str]: def test_bind_ioresult(): """Ensures that io ``Result`` can be bound.""" + def factory(inner_value: int) -> IOResult[int, str]: if inner_value > 0: return IOSuccess(inner_value + 1) @@ -58,6 +64,7 @@ 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[float, int]: return RequiresContext(lambda deps: inner_value / deps) @@ -73,6 +80,7 @@ def factory(inner_value: int) -> RequiresContext[float, int]: def test_bind_result_context(): """Ensures that ``RequiresContextResult`` can be bound.""" + def factory(inner_value: int) -> RequiresContextResult[float, str, int]: return RequiresContextResult(lambda deps: Success(inner_value / deps)) @@ -88,6 +96,7 @@ def factory(inner_value: int) -> RequiresContextResult[float, str, int]: def test_lash_success(): """Ensures that lash works for Success container.""" + def factory(inner_value) -> RCR[int, str, int]: return RCR.from_value(inner_value * 2) @@ -101,6 +110,7 @@ def factory(inner_value) -> RCR[int, str, int]: def test_lash_failure(): """Ensures that lash works for Failure container.""" + def factory(inner_value) -> RCR[int, str, int]: return RCR.from_failure(inner_value * 2) 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 7a2009316..520404e68 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,6 +5,7 @@ def test_bind(): """Ensures that bind works.""" + def factory(inner_value: int) -> RCR[float, str, int]: if inner_value > 0: return RCR(lambda deps: Success(inner_value / deps)) @@ -15,13 +16,18 @@ def factory(inner_value: int) -> RCR[float, str, int]: assert bound.bind(factory)(2) == factory(input_value)(2) assert bound.bind(factory)(2) == Success(2.5) - assert RCR.from_value(0).bind( - factory, - )(2) == factory(0)(2) == Failure('0') + assert ( + RCR.from_value(0).bind( + factory, + )(2) + == factory(0)(2) + == Failure('0') + ) def test_bind_regular_result(): """Ensures that regular ``Result`` can be bound.""" + def factory(inner_value: int) -> Result[int, str]: if inner_value > 0: return Success(inner_value + 1) @@ -39,6 +45,7 @@ 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[float, int]: return RequiresContext(lambda deps: inner_value / deps) @@ -54,6 +61,7 @@ def factory(inner_value: int) -> RequiresContext[float, int]: def test_lash_success(): """Ensures that lash works for Success container.""" + def factory(inner_value) -> RCR[int, str, int]: return RCR.from_value(inner_value * 2) @@ -67,6 +75,7 @@ def factory(inner_value) -> RCR[int, str, int]: def test_lash_failure(): """Ensures that lash works for Failure container.""" + def factory(inner_value) -> RCR[int, str, int]: return RCR.from_failure(inner_value * 2) diff --git a/tests/test_contrib/test_hypothesis/test_laws/test_custom_type_applicative.py b/tests/test_contrib/test_hypothesis/test_laws/test_custom_type_applicative.py index 481a67c80..34fad9e76 100644 --- a/tests/test_contrib/test_hypothesis/test_laws/test_custom_type_applicative.py +++ b/tests/test_contrib/test_hypothesis/test_laws/test_custom_type_applicative.py @@ -30,7 +30,7 @@ def apply( self, container: Kind1['_Wrapper', Callable[[_ValueType], _NewValueType]], ) -> '_Wrapper[_NewValueType]': - function = container._inner_value # noqa: WPS437 + function = container._inner_value # noqa: SLF001 return _Wrapper(function(self._inner_value)) @classmethod diff --git a/tests/test_contrib/test_hypothesis/test_laws/test_wrong_custom_type_with_init.py b/tests/test_contrib/test_hypothesis/test_laws/test_wrong_custom_type_with_init.py index 3efda4e38..f5f7f2400 100644 --- a/tests/test_contrib/test_hypothesis/test_laws/test_wrong_custom_type_with_init.py +++ b/tests/test_contrib/test_hypothesis/test_laws/test_wrong_custom_type_with_init.py @@ -29,7 +29,7 @@ def map( function: Callable[[_ValueType], _NewValueType], ) -> '_Wrapper[_NewValueType]': return _Wrapper( - 'wrong-{0}'.format(function(self._inner_value)), # type: ignore + f'wrong-{function(self._inner_value)}', # type: ignore ) diff --git a/tests/test_contrib/test_hypothesis/test_type_resolution.py b/tests/test_contrib/test_hypothesis/test_type_resolution.py index a9c922d58..72cadd05a 100644 --- a/tests/test_contrib/test_hypothesis/test_type_resolution.py +++ b/tests/test_contrib/test_hypothesis/test_type_resolution.py @@ -33,7 +33,6 @@ RequiresContextResult, RequiresContextIOResult, RequiresContextFutureResult, - # Aliases: ResultE, IOResultE, diff --git a/tests/test_contrib/test_pytest/test_plugin_error_handler.py b/tests/test_contrib/test_pytest/test_plugin_error_handler.py index 399468c9d..57e989fa8 100644 --- a/tests/test_contrib/test_pytest/test_plugin_error_handler.py +++ b/tests/test_contrib/test_pytest/test_plugin_error_handler.py @@ -18,54 +18,63 @@ def _under_test( should_lash: bool = False, ): if should_lash: - return container.lash(lambda inner: container.from_failure(inner)) - return container.bind(lambda inner: container.from_value(inner)) + return container.lash(container.from_failure) + return container.bind(container.from_value) -@pytest.mark.parametrize('container', [ - Success(1), - Failure(1), - IOSuccess(1), - IOFailure(1), - RequiresContextIOResult.from_value(1), - RequiresContextIOResult.from_failure(1), - RequiresContextFutureResult.from_value(1), - RequiresContextFutureResult.from_failure(1), - RequiresContextResult.from_value(1), - RequiresContextResult.from_failure(1), - FutureResult.from_value(1), - FutureResult.from_failure(1), -]) -@pytest.mark.parametrize('kwargs', [ - {'should_lash': True}, -]) +@pytest.mark.parametrize( + 'container', + [ + Success(1), + Failure(1), + IOSuccess(1), + IOFailure(1), + RequiresContextIOResult.from_value(1), + RequiresContextIOResult.from_failure(1), + RequiresContextFutureResult.from_value(1), + RequiresContextFutureResult.from_failure(1), + RequiresContextResult.from_value(1), + RequiresContextResult.from_failure(1), + FutureResult.from_value(1), + FutureResult.from_failure(1), + ], +) +@pytest.mark.parametrize( + 'kwargs', + [ + {'should_lash': True}, + ], +) def test_error_handled(returns: ReturnsAsserts, container, kwargs): """Demo on how to use ``pytest`` helpers to work with error handling.""" - assert not returns._errors_handled # noqa: WPS437 + assert not returns._errors_handled # noqa: SLF001 error_handled = _under_test(container, **kwargs) assert returns.is_error_handled(error_handled) assert returns.is_error_handled(error_handled.map(identity)) assert returns.is_error_handled(error_handled.alt(identity)) - assert returns._errors_handled # noqa: WPS437 + assert returns._errors_handled # noqa: SLF001 -@pytest.mark.parametrize('container', [ - Success(1), - Failure(1), - IOSuccess(1), - IOFailure(1), - RequiresContextIOResult.from_value(1), - RequiresContextIOResult.from_failure(1), - RequiresContextFutureResult.from_value(1), - RequiresContextFutureResult.from_failure(1), - RequiresContextResult.from_value(1), - RequiresContextResult.from_failure(1), -]) +@pytest.mark.parametrize( + 'container', + [ + Success(1), + Failure(1), + IOSuccess(1), + IOFailure(1), + RequiresContextIOResult.from_value(1), + RequiresContextIOResult.from_failure(1), + RequiresContextFutureResult.from_value(1), + RequiresContextFutureResult.from_failure(1), + RequiresContextResult.from_value(1), + RequiresContextResult.from_failure(1), + ], +) def test_error_not_handled(returns: ReturnsAsserts, container): """Demo on how to use ``pytest`` helpers to work with error handling.""" - assert not returns._errors_handled # noqa: WPS437 + assert not returns._errors_handled # noqa: SLF001 error_handled = _under_test(container) assert not returns.is_error_handled(container) @@ -73,16 +82,19 @@ def test_error_not_handled(returns: ReturnsAsserts, container): assert not returns.is_error_handled(error_handled.map(identity)) assert not returns.is_error_handled(error_handled.alt(identity)) - assert not returns._errors_handled # noqa: WPS437 + assert not returns._errors_handled # noqa: SLF001 @pytest.mark.anyio -@pytest.mark.parametrize('container', [ - FutureResult.from_value(1), - FutureResult.from_failure(1), - RequiresContextFutureResult.from_value(1), - RequiresContextFutureResult.from_failure(1), -]) +@pytest.mark.parametrize( + 'container', + [ + FutureResult.from_value(1), + FutureResult.from_failure(1), + RequiresContextFutureResult.from_value(1), + RequiresContextFutureResult.from_failure(1), + ], +) async def test_error_not_handled_async(returns: ReturnsAsserts, container): """Demo on how to use ``pytest`` helpers to work with error handling.""" error_handled = _under_test(container) diff --git a/tests/test_contrib/test_pytest/test_plugin_has_trace.py b/tests/test_contrib/test_pytest/test_plugin_has_trace.py index a99096be8..8cc4d26b4 100644 --- a/tests/test_contrib/test_pytest/test_plugin_has_trace.py +++ b/tests/test_contrib/test_pytest/test_plugin_has_trace.py @@ -11,78 +11,104 @@ def _create_container_function(container_type, container_value): def _create_container_function_intermediate(container_type, container_value): return _create_container_function( # type: ignore - container_type, container_value, + container_type, + container_value, ) @safe -def _safe_decorated_function(return_failure: bool = False): +def _safe_decorated_function(*, return_failure: bool = False): if return_failure: raise ValueError('Function failed') -@pytest.mark.parametrize('container_type', [ # noqa: WPS118 - Success, - Failure, - IOSuccess, - IOFailure, -]) +@pytest.mark.parametrize( + 'container_type', + [ # noqa: WPS118 + Success, + Failure, + IOSuccess, + IOFailure, + ], +) def test_assert_trace1(container_type, returns: ReturnsAsserts): """Test if our plugin will identify the container creation correctly.""" with returns.assert_trace(container_type, _create_container_function): _create_container_function(container_type, 1) # type: ignore -@pytest.mark.parametrize('container_type', [ # noqa: WPS118 - Success, - Failure, - IOSuccess, - IOFailure, -]) +@pytest.mark.parametrize( + 'container_type', + [ # noqa: WPS118 + Success, + Failure, + IOSuccess, + IOFailure, + ], +) def test_assert_trace2(container_type, returns: ReturnsAsserts): """Test if our plugin will identify the container creation correctly.""" with returns.assert_trace(container_type, _create_container_function): _create_container_function_intermediate( # type: ignore - container_type, 1, + container_type, + 1, ) -@pytest.mark.parametrize(('desired_type', 'wrong_type'), [ - (Success, Failure), - (Failure, Success), - (IOSuccess, IOFailure), - (IOFailure, IOSuccess), -]) +@pytest.mark.parametrize( + ('desired_type', 'wrong_type'), + [ + (Success, Failure), + (Failure, Success), + (IOSuccess, IOFailure), + (IOFailure, IOSuccess), + ], +) def test_failed_assert_trace1( - desired_type, wrong_type, returns: ReturnsAsserts, + desired_type, + wrong_type, + returns: ReturnsAsserts, ): """Test if our plugin will identify the container was not created.""" - with pytest.raises(pytest.fail.Exception): # noqa: PT012 - with returns.assert_trace(desired_type, _create_container_function): - _create_container_function(wrong_type, 1) # type: ignore - - -@pytest.mark.parametrize(('desired_type', 'wrong_type'), [ - (Success, Failure), - (Failure, Success), - (IOSuccess, IOFailure), - (IOFailure, IOSuccess), -]) + with ( + pytest.raises(pytest.fail.Exception), + returns.assert_trace(desired_type, _create_container_function), + ): + _create_container_function(wrong_type, 1) # type: ignore + + +@pytest.mark.parametrize( + ('desired_type', 'wrong_type'), + [ + (Success, Failure), + (Failure, Success), + (IOSuccess, IOFailure), + (IOFailure, IOSuccess), + ], +) def test_failed_assert_trace2( - desired_type, wrong_type, returns: ReturnsAsserts, + desired_type, + wrong_type, + returns: ReturnsAsserts, ): """Test if our plugin will identify the container was not created.""" - with pytest.raises(pytest.fail.Exception): # noqa: PT012 - with returns.assert_trace(desired_type, _create_container_function): - _create_container_function_intermediate( # type: ignore - wrong_type, 1, - ) + with ( + pytest.raises(pytest.fail.Exception), + returns.assert_trace(desired_type, _create_container_function), + ): + _create_container_function_intermediate( # type: ignore + wrong_type, + 1, + ) -@pytest.mark.parametrize('container_type', [ # noqa: WPS118 - Success, - Failure, -]) +@pytest.mark.parametrize( + 'container_type', + [ # noqa: WPS118 + Success, + Failure, + ], +) def test_safe_decorated_assert(container_type, returns: ReturnsAsserts): """Test if our plugin will catch containers from @safe-wrapped functions.""" with returns.assert_trace(container_type, _safe_decorated_function): diff --git a/tests/test_converters/test_flatten.py b/tests/test_converters/test_flatten.py index a38c800d2..cc4470e6a 100644 --- a/tests/test_converters/test_flatten.py +++ b/tests/test_converters/test_flatten.py @@ -13,50 +13,49 @@ from returns.result import Failure, Success -@pytest.mark.parametrize(('container', 'merged'), [ - # Flattens: - (IO(IO(1)), IO(1)), - - (Success(Success({})), Success({})), - (IOSuccess(IOSuccess(1)), IOSuccess(1)), - - (Some(Some(None)), Some(None)), - (Some(Some([])), Some([])), - - # Nope: - (Nothing, Nothing), - (Failure(Failure('a')), Failure(Failure('a'))), - (Failure(Success('a')), Failure(Success('a'))), - (IOFailure(IOFailure('a')), IOFailure(IOFailure('a'))), - (IOFailure(IOSuccess('a')), IOFailure(IOSuccess('a'))), -]) +@pytest.mark.parametrize( + ('container', 'merged'), + [ + # Flattens: + (IO(IO(1)), IO(1)), + (Success(Success({})), Success({})), + (IOSuccess(IOSuccess(1)), IOSuccess(1)), + (Some(Some(None)), Some(None)), + (Some(Some([])), Some([])), + # Nope: + (Nothing, Nothing), + (Failure(Failure('a')), Failure(Failure('a'))), + (Failure(Success('a')), Failure(Success('a'))), + (IOFailure(IOFailure('a')), IOFailure(IOFailure('a'))), + (IOFailure(IOSuccess('a')), IOFailure(IOSuccess('a'))), + ], +) def test_flatten(container, merged): """Ensures that `flatten` is always returning the correct type.""" assert flatten(container) == merged -@pytest.mark.parametrize(('container', 'merged'), [ - ( - RequiresContextResult.from_value( +@pytest.mark.parametrize( + ('container', 'merged'), + [ + ( + RequiresContextResult.from_value( + RequiresContextResult.from_value(1), + ), RequiresContextResult.from_value(1), ), - - RequiresContextResult.from_value(1), - ), - - ( - RequiresContextIOResult.from_value( + ( + RequiresContextIOResult.from_value( + RequiresContextIOResult.from_value(1), + ), RequiresContextIOResult.from_value(1), ), - - RequiresContextIOResult.from_value(1), - ), - - ( - RequiresContext.from_value(RequiresContext.from_value(1)), - RequiresContext.from_value(1), - ), -]) + ( + RequiresContext.from_value(RequiresContext.from_value(1)), + RequiresContext.from_value(1), + ), + ], +) def test_flatten_context(container, merged): """Ensures that `flatten` is always returning the correct type.""" assert flatten(container)(...) == merged(...) @@ -111,7 +110,7 @@ async def test_non_flatten_future(subtests): for cont in futures: with subtests.test(container=cont): assert isinstance( - (await flatten(cont)).failure()._inner_value, # noqa: WPS437 + (await flatten(cont)).failure()._inner_value, # noqa: SLF001 cont.__class__, ) @@ -133,6 +132,6 @@ async def test_non_flatten_context_future_result(subtests): with subtests.test(container=cont): inner = await flatten(cont)(...) assert isinstance( - inner.failure()._inner_value, # noqa: WPS437 + inner.failure()._inner_value, # noqa: SLF001 cont.__class__, ) diff --git a/tests/test_curry/test_curry.py b/tests/test_curry/test_curry.py index 64387c042..8cdb82720 100644 --- a/tests/test_curry/test_curry.py +++ b/tests/test_curry/test_curry.py @@ -141,7 +141,7 @@ def test_arg_star_kwargs(): @curry def factory(first: int, **kwargs: int) -> list[tuple[str, int]]: - return [('first', first)] + sorted(kwargs.items()) + return [('first', first), *sorted(kwargs.items())] assert factory(1) == [('first', 1)] assert factory(1, arg=2) == [('first', 1), ('arg', 2)] @@ -168,12 +168,14 @@ def test_kwonly(): @curry def factory(*args: int, by: int) -> tuple[int, ...]: - return args + (by, ) + return (*args, by) assert factory( - 1, 2, 3, + 1, + 2, + 3, )(by=10) == (1, 2, 3, 10) - assert factory(by=10) == (10, ) + assert factory(by=10) == (10,) def test_raises(): diff --git a/tests/test_examples/test_context/test_reader_future_result.py b/tests/test_examples/test_context/test_reader_future_result.py index 8eba31fab..11ffe9c7a 100644 --- a/tests/test_examples/test_context/test_reader_future_result.py +++ b/tests/test_examples/test_context/test_reader_future_result.py @@ -37,19 +37,23 @@ def _fetch_post( httpx.AsyncClient, ] = RequiresContextFutureResultE.ask() - return context.bind_future_result( - lambda client: future_safe(client.get)(_URL.format(post_id)), - ).bind_result( - safe(tap(httpx.Response.raise_for_status)), - ).map( - lambda response: cast(_Post, response.json()), # or validate it + return ( + context.bind_future_result( + lambda client: future_safe(client.get)(_URL.format(post_id)), + ) + .bind_result( + safe(tap(httpx.Response.raise_for_status)), + ) + .map( + lambda response: cast(_Post, response.json()), # or validate it + ) ) def _show_titles( number_of_posts: int, ) -> RequiresContextFutureResultE[Sequence[str], httpx.AsyncClient]: - def factory(post: _Post) -> str: + def factory(post: _Post) -> str: # noqa: FURB118 return post['title'] titles = [ diff --git a/tests/test_examples/test_future/test_future_result.py b/tests/test_examples/test_future/test_future_result.py index 13bcf3480..7b0c27a29 100644 --- a/tests/test_examples/test_future/test_future_result.py +++ b/tests/test_examples/test_future/test_future_result.py @@ -28,10 +28,10 @@ async def _fetch_post(post_id: int) -> _Post: return cast(_Post, response.json()) # or validate the response -def _show_titles(number_of_posts: int) -> Sequence[ - FutureResult[str, Exception] -]: - def factory(post: _Post) -> str: +def _show_titles( + number_of_posts: int, +) -> Sequence[FutureResult[str, Exception]]: + def factory(post: _Post) -> str: # noqa: FURB118 return post['title'] return [ diff --git a/tests/test_examples/test_io/test_ioresult_container/test_ioresult_pattern_matching.py b/tests/test_examples/test_io/test_ioresult_container/test_ioresult_pattern_matching.py index b9c44cd60..6b23060b2 100644 --- a/tests/test_examples/test_io/test_ioresult_container/test_ioresult_pattern_matching.py +++ b/tests/test_examples/test_io/test_ioresult_container/test_ioresult_pattern_matching.py @@ -13,7 +13,7 @@ # Matches any `IOSuccess` instance # and binds its value to the `value` variable case IOSuccess(value): - print('Result is "{0}"'.format(value)) + print(f'Result is "{value}"') # Matches any `IOFailure` instance case IOFailure(_): diff --git a/tests/test_examples/test_maybe/test_maybe_pattern_matching.py b/tests/test_examples/test_maybe/test_maybe_pattern_matching.py index 4b9bcf034..d311bd011 100644 --- a/tests/test_examples/test_maybe/test_maybe_pattern_matching.py +++ b/tests/test_examples/test_maybe/test_maybe_pattern_matching.py @@ -34,7 +34,7 @@ def _find_book(book_id: int) -> Maybe[_Book]: # Matches any `Some` instance and binds its value to the `book` variable case Some(book): - print('Book found: {0}'.format(book.name)) + print(f'Book found: {book.name}') # Matches `Nothing` instance case Maybe.empty: diff --git a/tests/test_examples/test_result/test_result_pattern_matching.py b/tests/test_examples/test_result/test_result_pattern_matching.py index 1b0275a6f..b0ffc5051 100644 --- a/tests/test_examples/test_result/test_result_pattern_matching.py +++ b/tests/test_examples/test_result/test_result_pattern_matching.py @@ -2,7 +2,7 @@ @safe -def div(first_number: int, second_number: int) -> int: +def div(first_number: int, second_number: int) -> int: # noqa: FURB118 return first_number // second_number @@ -13,7 +13,7 @@ def div(first_number: int, second_number: int) -> int: # Matches any `Success` instance and binds its value to the `value` variable case Success(value): - print('Result is "{0}"'.format(value)) + print(f'Result is "{value}"') # Matches if the result stored inside `Failure` is `ZeroDivisionError` case Failure(ZeroDivisionError()): diff --git a/tests/test_functions/test_raise_exception.py b/tests/test_functions/test_raise_exception.py index 2d31ba186..393df2458 100644 --- a/tests/test_functions/test_raise_exception.py +++ b/tests/test_functions/test_raise_exception.py @@ -1,19 +1,21 @@ - import pytest from returns.functions import raise_exception from returns.result import Failure, Success -class _CustomException(Exception): +class _CustomError(Exception): """Just for the test.""" -@pytest.mark.parametrize('exception_type', [ - TypeError, - ValueError, - _CustomException, -]) +@pytest.mark.parametrize( + 'exception_type', + [ + TypeError, + ValueError, + _CustomError, + ], +) def test_raise_regular_exception(exception_type: type[Exception]): """Ensures that regular exception can be thrown.""" with pytest.raises(exception_type): diff --git a/tests/test_future/test_future_container/test_future_decorator.py b/tests/test_future/test_future_container/test_future_decorator.py index abd898a16..f188f9f81 100644 --- a/tests/test_future/test_future_container/test_future_decorator.py +++ b/tests/test_future/test_future_container/test_future_decorator.py @@ -1,3 +1,4 @@ +import anyio import pytest from returns.future import Future, future @@ -6,6 +7,8 @@ @future async def _coro(arg: int) -> float: + assert isinstance(arg, int) + await anyio.sleep(0) return arg / 2 diff --git a/tests/test_future/test_future_result/test_future_result_decorator.py b/tests/test_future/test_future_result/test_future_result_decorator.py index ef7a0a716..3982f9ba5 100644 --- a/tests/test_future/test_future_result/test_future_result_decorator.py +++ b/tests/test_future/test_future_result/test_future_result_decorator.py @@ -1,4 +1,4 @@ - +import anyio import pytest from returns.future import FutureResult, future_safe @@ -7,17 +7,22 @@ @future_safe async def _coro(arg: int) -> float: + assert isinstance(arg, int) + await anyio.sleep(0) return 1 / arg @future_safe(exceptions=(ZeroDivisionError,)) async def _coro_two(arg: int) -> float: + assert isinstance(arg, int) + await anyio.sleep(0) return 1 / arg @future_safe((ZeroDivisionError,)) async def _coro_three(arg: int | str) -> float: assert isinstance(arg, int) + await anyio.sleep(0) return 1 / arg diff --git a/tests/test_future/test_future_result/test_future_result_units.py b/tests/test_future/test_future_result/test_future_result_units.py index ac92fc2ec..15c07c0d0 100644 --- a/tests/test_future/test_future_result/test_future_result_units.py +++ b/tests/test_future/test_future_result/test_future_result_units.py @@ -14,16 +14,12 @@ async def test_inner_value(subtests): # And they have to be fresh. That's why we use subtests for it. FutureResult.from_value(1), FutureResult.from_failure(1), - FutureResult.from_io(IO(1)), FutureResult.from_failed_io(IO(1)), - FutureResult.from_ioresult(IOSuccess(1)), FutureResult.from_ioresult(IOFailure(1)), - FutureResult.from_result(Success(1)), FutureResult.from_result(Failure(1)), - FutureResult.from_future(Future.from_value(1)), FutureResult.from_failed_future(Future.from_value(1)), FutureResult.from_typecast(Future.from_value(Success(1))), @@ -31,4 +27,4 @@ async def test_inner_value(subtests): for container in containers: with subtests.test(container=container): result_inst = await container - assert result_inst._inner_value._inner_value == 1 # noqa: WPS437 + assert result_inst._inner_value._inner_value == 1 # noqa: SLF001 diff --git a/tests/test_io/test_io_container/test_io.py b/tests/test_io/test_io_container/test_io.py index e6aa9c1a5..fbb299f8b 100644 --- a/tests/test_io/test_io_container/test_io.py +++ b/tests/test_io/test_io_container/test_io.py @@ -26,10 +26,13 @@ def test_io_str(): assert str(IO([])) == '' -@pytest.mark.parametrize('container', [ - IOSuccess(1), - IOFailure(1), -]) +@pytest.mark.parametrize( + 'container', + [ + IOSuccess(1), + IOFailure(1), + ], +) def test_io_typecast_reverse(container): """Ensures that IO can be casted to IOResult and back.""" assert IO.from_ioresult(container) == IO.from_ioresult( diff --git a/tests/test_io/test_io_container/test_io_pickle.py b/tests/test_io/test_io_container/test_io_pickle.py index fb191214d..5924c2517 100644 --- a/tests/test_io/test_io_container/test_io_pickle.py +++ b/tests/test_io/test_io_container/test_io_pickle.py @@ -3,11 +3,11 @@ def test_io_pickle(): """Tests how pickle protocol works for containers.""" - assert IO(1).__getstate__() == {'container_value': 1} # noqa: WPS609 + assert IO(1).__getstate__() == {'container_value': 1} def test_io_pickle_restore(): """Ensures that object can be restored.""" container = IO(2) - container.__setstate__({'container_value': 1}) # noqa: WPS609, E501 + container.__setstate__({'container_value': 1}) assert container == IO(1) diff --git a/tests/test_io/test_ioresult_container/test_ioresult_bind.py b/tests/test_io/test_ioresult_container/test_ioresult_bind.py index 9801c1cd1..69a4461de 100644 --- a/tests/test_io/test_ioresult_container/test_ioresult_bind.py +++ b/tests/test_io/test_ioresult_container/test_ioresult_bind.py @@ -4,6 +4,7 @@ def test_bind(): """Ensures that bind works.""" + def factory(inner_value: int) -> IOResult[int, str]: if inner_value > 0: return IOSuccess(inner_value * 2) @@ -24,6 +25,7 @@ def factory(inner_value: int) -> IOResult[int, str]: def test_left_identity_success(): """Ensures that left identity works for IOSuccess container.""" + def factory(inner_value: int) -> IOResult[int, str]: return IOSuccess(inner_value * 2) @@ -35,6 +37,7 @@ def factory(inner_value: int) -> IOResult[int, str]: def test_left_identity_failure(): """Ensures that left identity works for IOFailure container.""" + def factory(inner_value: int) -> IOResult[int, int]: return IOFailure(6) @@ -46,6 +49,7 @@ def factory(inner_value: int) -> IOResult[int, int]: def test_bind_regular_result(): """Ensures that regular ``Result`` can be bound to ``IOResult``.""" + def factory(inner_value: int) -> Result[int, str]: if inner_value > 0: return Success(inner_value + 1) @@ -62,16 +66,16 @@ def factory(inner_value: int) -> Result[int, str]: def test_lash_success(): """Ensures that lash works for IOSuccess container.""" + def factory(inner_value) -> IOResult[int, str]: return IOSuccess(inner_value * 2) - bound = IOSuccess(5).lash(factory) - - assert bound == IOSuccess(5) + assert IOSuccess(5).lash(factory) == IOSuccess(5) def test_lash_failure(): """Ensures that lash works for IOFailure container.""" + def factory(inner_value: int) -> IOResult[str, int]: return IOFailure(inner_value + 1) diff --git a/tests/test_io/test_ioresult_container/test_ioresult_functions/test_impure_safe.py b/tests/test_io/test_ioresult_container/test_ioresult_functions/test_impure_safe.py index 80251273c..0ad153a2d 100644 --- a/tests/test_io/test_ioresult_container/test_ioresult_functions/test_impure_safe.py +++ b/tests/test_io/test_ioresult_container/test_ioresult_functions/test_impure_safe.py @@ -1,4 +1,3 @@ - import pytest from returns.io import IOSuccess, impure_safe @@ -30,7 +29,8 @@ def test_safe_iofailure(): """Ensures that safe decorator works correctly for IOFailure case.""" failed = _function(0) assert isinstance( - failed.failure()._inner_value, ZeroDivisionError, # noqa: WPS437 + failed.failure()._inner_value, # noqa: SLF001 + ZeroDivisionError, ) @@ -38,13 +38,13 @@ def test_safe_failure_with_expected_error(): """Ensures that safe decorator works correctly for Failure case.""" failed = _function_two(0) assert isinstance( - failed.failure()._inner_value, # noqa: WPS437 + failed.failure()._inner_value, # noqa: SLF001 ZeroDivisionError, ) failed2 = _function_three(0) assert isinstance( - failed2.failure()._inner_value, # noqa: WPS437 + failed2.failure()._inner_value, # noqa: SLF001 ZeroDivisionError, ) diff --git a/tests/test_iterables/test_fold/test_collect.py b/tests/test_iterables/test_fold/test_collect.py index 9688f392c..64c3f21f8 100644 --- a/tests/test_iterables/test_fold/test_collect.py +++ b/tests/test_iterables/test_fold/test_collect.py @@ -17,98 +17,98 @@ from returns.result import Failure, Success -@pytest.mark.parametrize(('iterable', 'sequence'), [ - # Regular types: - - ([], IO(())), - ([IO(1)], IO((1,))), - ([IO(1), IO(2)], IO((1, 2))), - - # Can fail: - - ([], Success(())), - ([Success(1)], Success((1,))), - ([Success(1), Success(2)], Success((1, 2))), - ( - [Failure('a'), Success(1), Success(2)], - Failure('a'), - ), - ([Success(1), Failure('a')], Failure('a')), - ([Failure('a'), Failure('b')], Failure('a')), - - ([], Some(())), - ([Some(1)], Some((1,))), - ([Some(1), Some(2)], Some((1, 2))), - ([Nothing, Some(1), Some(2)], Nothing), - ([Some(1), Nothing, Some(2)], Nothing), - ([Some(1), Some(2), Nothing], Nothing), - ([Nothing], Nothing), - - ([], IOSuccess(())), - ([IOSuccess(1)], IOSuccess((1,))), - ([IOSuccess(1), IOSuccess(2)], IOSuccess((1, 2))), - ( - [IOFailure('a'), IOSuccess(1), IOSuccess(2)], - IOFailure('a'), - ), - ([IOSuccess(1), IOFailure('a')], IOFailure('a')), - ([IOFailure('a'), IOFailure('b')], IOFailure('a')), -]) +@pytest.mark.parametrize( + ('iterable', 'sequence'), + [ + # Regular types: + ([], IO(())), + ([IO(1)], IO((1,))), + ([IO(1), IO(2)], IO((1, 2))), + # Can fail: + ([], Success(())), + ([Success(1)], Success((1,))), + ([Success(1), Success(2)], Success((1, 2))), + ( + [Failure('a'), Success(1), Success(2)], + Failure('a'), + ), + ([Success(1), Failure('a')], Failure('a')), + ([Failure('a'), Failure('b')], Failure('a')), + ([], Some(())), + ([Some(1)], Some((1,))), + ([Some(1), Some(2)], Some((1, 2))), + ([Nothing, Some(1), Some(2)], Nothing), + ([Some(1), Nothing, Some(2)], Nothing), + ([Some(1), Some(2), Nothing], Nothing), + ([Nothing], Nothing), + ([], IOSuccess(())), + ([IOSuccess(1)], IOSuccess((1,))), + ([IOSuccess(1), IOSuccess(2)], IOSuccess((1, 2))), + ( + [IOFailure('a'), IOSuccess(1), IOSuccess(2)], + IOFailure('a'), + ), + ([IOSuccess(1), IOFailure('a')], IOFailure('a')), + ([IOFailure('a'), IOFailure('b')], IOFailure('a')), + ], +) def test_fold_collect(iterable, sequence): """Iterable for regular types and ``Fold``.""" assert Fold.collect(iterable, sequence.from_value(())) == sequence -@pytest.mark.parametrize(('iterable', 'sequence'), [ - # Regular types: - - ([], Reader.from_value(())), - ([Reader.from_value(1)], Reader.from_value((1,))), - ( - [Reader.from_value(1), Reader.from_value(2)], - Reader.from_value((1, 2)), - ), - - # Can fail: - - ([], ReaderResult.from_value(())), - ([ReaderResult.from_value(1)], ReaderResult.from_value((1,))), - ( - [ReaderResult.from_value(1), ReaderResult.from_value(2)], - ReaderResult.from_value((1, 2)), - ), - ( - [ +@pytest.mark.parametrize( + ('iterable', 'sequence'), + [ + # Regular types: + ([], Reader.from_value(())), + ([Reader.from_value(1)], Reader.from_value((1,))), + ( + [Reader.from_value(1), Reader.from_value(2)], + Reader.from_value((1, 2)), + ), + # Can fail: + ([], ReaderResult.from_value(())), + ([ReaderResult.from_value(1)], ReaderResult.from_value((1,))), + ( + [ReaderResult.from_value(1), ReaderResult.from_value(2)], + ReaderResult.from_value((1, 2)), + ), + ( + [ + ReaderResult.from_failure('a'), + ReaderResult.from_value(1), + ReaderResult.from_value(2), + ], ReaderResult.from_failure('a'), - ReaderResult.from_value(1), - ReaderResult.from_value(2), - ], - ReaderResult.from_failure('a'), - ), - ( - [ReaderResult.from_failure('a'), ReaderResult.from_failure('b')], - ReaderResult.from_failure('a'), - ), - - ([], ReaderIOResult.from_value(())), - ([ReaderIOResult.from_value(1)], ReaderIOResult.from_value((1,))), - ( - [ReaderIOResult.from_value(1), ReaderIOResult.from_value(2)], - ReaderIOResult.from_value((1, 2)), - ), - ( - [ + ), + ( + [ReaderResult.from_failure('a'), ReaderResult.from_failure('b')], + ReaderResult.from_failure('a'), + ), + ([], ReaderIOResult.from_value(())), + ([ReaderIOResult.from_value(1)], ReaderIOResult.from_value((1,))), + ( + [ReaderIOResult.from_value(1), ReaderIOResult.from_value(2)], + ReaderIOResult.from_value((1, 2)), + ), + ( + [ + ReaderIOResult.from_failure('a'), + ReaderIOResult.from_value(1), + ReaderIOResult.from_value(2), + ], ReaderIOResult.from_failure('a'), - ReaderIOResult.from_value(1), - ReaderIOResult.from_value(2), - ], - ReaderIOResult.from_failure('a'), - ), - ( - [ReaderIOResult.from_failure('a'), ReaderIOResult.from_failure('b')], - ReaderIOResult.from_failure('a'), - ), -]) + ), + ( + [ + ReaderIOResult.from_failure('a'), + ReaderIOResult.from_failure('b'), + ], + ReaderIOResult.from_failure('a'), + ), + ], +) def test_fold_collect_reader(iterable, sequence): """Ensures that ``.collect`` works for readers.""" assert Fold.collect( @@ -120,10 +120,12 @@ def test_fold_collect_reader(iterable, sequence): @pytest.mark.anyio async def test_fold_collect_reader_future_result(subtests): """Iterable for ``ReaderFutureResult`` and ``Fold``.""" - containers: list[tuple[ # noqa: WPS234 - Iterable[ReaderFutureResult[int, str, NoDeps]], - ReaderFutureResult[Sequence[int], str, NoDeps], - ]] = [ + containers: list[ + tuple[ # noqa: WPS234 + Iterable[ReaderFutureResult[int, str, NoDeps]], + ReaderFutureResult[Sequence[int], str, NoDeps], + ] + ] = [ ([], ReaderFutureResult.from_value(())), ( [ReaderFutureResult.from_value(1)], @@ -155,17 +157,20 @@ async def test_fold_collect_reader_future_result(subtests): for iterable, sequence in containers: with subtests.test(iterable=iterable, sequence=sequence): assert await Fold.collect( - iterable, sequence.from_value(()), + iterable, + sequence.from_value(()), )(...) == await sequence(...) @pytest.mark.anyio async def test_fold_collect_future(subtests): """Iterable for ``Future`` and ``Fold``.""" - containers: list[tuple[ # noqa: WPS234 - Iterable[Future[int]], - Future[Sequence[int]], - ]] = [ + containers: list[ + tuple[ # noqa: WPS234 + Iterable[Future[int]], + Future[Sequence[int]], + ] + ] = [ ([], Future.from_value(())), ([Future.from_value(1)], Future.from_value((1,))), ( @@ -175,18 +180,24 @@ async def test_fold_collect_future(subtests): ] for iterable, sequence in containers: with subtests.test(iterable=iterable, sequence=sequence): - assert await Fold.collect( - iterable, sequence.from_value(()), - ) == await sequence + assert ( + await Fold.collect( + iterable, + sequence.from_value(()), + ) + == await sequence + ) @pytest.mark.anyio async def test_fold_collect_future_result(subtests): """Iterable for ``FutureResult`` and ``Fold``.""" - containers: list[tuple[ # noqa: WPS234 - Iterable[FutureResult[int, str]], - FutureResult[Sequence[int], str], - ]] = [ + containers: list[ + tuple[ # noqa: WPS234 + Iterable[FutureResult[int, str]], + FutureResult[Sequence[int], str], + ] + ] = [ ([], FutureSuccess(())), ([FutureSuccess(1)], FutureSuccess((1,))), ([FutureSuccess(1), FutureSuccess(2)], FutureSuccess((1, 2))), @@ -198,9 +209,13 @@ async def test_fold_collect_future_result(subtests): ] for iterable, sequence in containers: with subtests.test(iterable=iterable, sequence=sequence): - assert await Fold.collect( - iterable, sequence.from_value(()), - ) == await sequence + assert ( + await Fold.collect( + iterable, + sequence.from_value(()), + ) + == await sequence + ) def test_fold_collect_recursion_limit(): diff --git a/tests/test_iterables/test_fold/test_collect_all.py b/tests/test_iterables/test_fold/test_collect_all.py index 70eaf391a..e894c3cc7 100644 --- a/tests/test_iterables/test_fold/test_collect_all.py +++ b/tests/test_iterables/test_fold/test_collect_all.py @@ -16,93 +16,102 @@ from returns.result import Failure, Success -@pytest.mark.parametrize(('iterable', 'sequence'), [ - ([], Some(())), - ([Some(1)], Some((1,))), - ([Some(1), Some(2)], Some((1, 2))), - ([Nothing, Some(1), Some(2)], Some((1, 2))), - ([Some(1), Nothing, Some(2)], Some((1, 2))), - ([Some(1), Some(2), Nothing], Some((1, 2))), - ([Nothing], Some(())), - - ([], Success(())), - ([Success(1)], Success((1,))), - ([Success(1), Success(2)], Success((1, 2))), - ( - [Failure('a'), Success(1), Success(2)], - Success((1, 2)), - ), - ([Success(1), Failure('b')], Success((1,))), - ([Failure('a'), Failure('b')], Success(())), - - ([], IOSuccess(())), - ([IOSuccess(1)], IOSuccess((1,))), - ([IOSuccess(1), IOSuccess(2)], IOSuccess((1, 2))), - ( - [IOFailure('a'), IOSuccess(1), IOSuccess(2)], - IOSuccess((1, 2)), - ), - ([IOSuccess(1), IOFailure('b')], IOSuccess((1,))), - ([IOFailure('a'), IOFailure('b')], IOSuccess(())), -]) +@pytest.mark.parametrize( + ('iterable', 'sequence'), + [ + ([], Some(())), + ([Some(1)], Some((1,))), + ([Some(1), Some(2)], Some((1, 2))), + ([Nothing, Some(1), Some(2)], Some((1, 2))), + ([Some(1), Nothing, Some(2)], Some((1, 2))), + ([Some(1), Some(2), Nothing], Some((1, 2))), + ([Nothing], Some(())), + ([], Success(())), + ([Success(1)], Success((1,))), + ([Success(1), Success(2)], Success((1, 2))), + ( + [Failure('a'), Success(1), Success(2)], + Success((1, 2)), + ), + ([Success(1), Failure('b')], Success((1,))), + ([Failure('a'), Failure('b')], Success(())), + ([], IOSuccess(())), + ([IOSuccess(1)], IOSuccess((1,))), + ([IOSuccess(1), IOSuccess(2)], IOSuccess((1, 2))), + ( + [IOFailure('a'), IOSuccess(1), IOSuccess(2)], + IOSuccess((1, 2)), + ), + ([IOSuccess(1), IOFailure('b')], IOSuccess((1,))), + ([IOFailure('a'), IOFailure('b')], IOSuccess(())), + ], +) def test_collect_all_result(iterable, sequence): """Iterable for ``Result`` and ``Fold``.""" assert Fold.collect_all(iterable, sequence.from_value(())) == sequence -@pytest.mark.parametrize(('iterable', 'sequence'), [ - ([], ReaderResult.from_value(())), - ([ReaderResult.from_value(1)], ReaderResult.from_value((1,))), - ( - [ReaderResult.from_value(1), ReaderResult.from_value(2)], - ReaderResult.from_value((1, 2)), - ), - ( - [ - ReaderResult.from_failure('a'), - ReaderResult.from_value(1), - ReaderResult.from_value(2), - ], - ReaderResult.from_value((1, 2)), - ), - ( - [ReaderResult.from_failure('a'), ReaderResult.from_failure('b')], - ReaderResult.from_value(()), - ), - - ([], ReaderIOResult.from_value(())), - ([ReaderIOResult.from_value(1)], ReaderIOResult.from_value((1,))), - ( - [ReaderIOResult.from_value(1), ReaderIOResult.from_value(2)], - ReaderIOResult.from_value((1, 2)), - ), - ( - [ - ReaderIOResult.from_failure('a'), - ReaderIOResult.from_value(1), - ReaderIOResult.from_value(2), - ], - ReaderIOResult.from_value((1, 2)), - ), - ( - [ReaderIOResult.from_failure('a'), ReaderIOResult.from_failure('b')], - ReaderIOResult.from_value(()), - ), -]) +@pytest.mark.parametrize( + ('iterable', 'sequence'), + [ + ([], ReaderResult.from_value(())), + ([ReaderResult.from_value(1)], ReaderResult.from_value((1,))), + ( + [ReaderResult.from_value(1), ReaderResult.from_value(2)], + ReaderResult.from_value((1, 2)), + ), + ( + [ + ReaderResult.from_failure('a'), + ReaderResult.from_value(1), + ReaderResult.from_value(2), + ], + ReaderResult.from_value((1, 2)), + ), + ( + [ReaderResult.from_failure('a'), ReaderResult.from_failure('b')], + ReaderResult.from_value(()), + ), + ([], ReaderIOResult.from_value(())), + ([ReaderIOResult.from_value(1)], ReaderIOResult.from_value((1,))), + ( + [ReaderIOResult.from_value(1), ReaderIOResult.from_value(2)], + ReaderIOResult.from_value((1, 2)), + ), + ( + [ + ReaderIOResult.from_failure('a'), + ReaderIOResult.from_value(1), + ReaderIOResult.from_value(2), + ], + ReaderIOResult.from_value((1, 2)), + ), + ( + [ + ReaderIOResult.from_failure('a'), + ReaderIOResult.from_failure('b'), + ], + ReaderIOResult.from_value(()), + ), + ], +) def test_collect_all_reader_result(iterable, sequence): """Iterable for ``ReaderResult`` and ``Fold``.""" assert Fold.collect_all( - iterable, sequence.from_value(()), + iterable, + sequence.from_value(()), )(...) == sequence(...) @pytest.mark.anyio async def test_collect_all_reader_future_result(subtests): """Iterable for ``ReaderFutureResult`` and ``Fold``.""" - containers: list[tuple[ # noqa: WPS234 - Iterable[ReaderFutureResult[int, str, NoDeps]], - ReaderFutureResult[Sequence[int], str, NoDeps], - ]] = [ + containers: list[ + tuple[ # noqa: WPS234 + Iterable[ReaderFutureResult[int, str, NoDeps]], + ReaderFutureResult[Sequence[int], str, NoDeps], + ] + ] = [ ([], ReaderFutureResult.from_value(())), ( [ReaderFutureResult.from_value(1)], @@ -134,17 +143,20 @@ async def test_collect_all_reader_future_result(subtests): for iterable, sequence in containers: with subtests.test(iterable=iterable, sequence=sequence): assert await Fold.collect_all( - iterable, sequence.from_value(()), + iterable, + sequence.from_value(()), )(...) == await sequence(...) @pytest.mark.anyio async def test_collect_all_future_result(subtests): """Iterable for ``FutureResult`` and ``Fold``.""" - containers: list[tuple[ # noqa: WPS234 - Iterable[FutureResult[int, str]], - FutureResult[Sequence[int], str], - ]] = [ + containers: list[ + tuple[ # noqa: WPS234 + Iterable[FutureResult[int, str]], + FutureResult[Sequence[int], str], + ] + ] = [ ([], FutureSuccess(())), ([FutureSuccess(1)], FutureSuccess((1,))), ([FutureSuccess(1), FutureSuccess(2)], FutureSuccess((1, 2))), @@ -156,9 +168,13 @@ async def test_collect_all_future_result(subtests): ] for iterable, sequence in containers: with subtests.test(iterable=iterable, sequence=sequence): - assert await Fold.collect_all( - iterable, sequence.from_value(()), - ) == await sequence + assert ( + await Fold.collect_all( + iterable, + sequence.from_value(()), + ) + == await sequence + ) def test_fold_collect_recursion_limit(): diff --git a/tests/test_iterables/test_fold/test_loop.py b/tests/test_iterables/test_fold/test_loop.py index 6b3ac6f03..2f0e429f2 100644 --- a/tests/test_iterables/test_fold/test_loop.py +++ b/tests/test_iterables/test_fold/test_loop.py @@ -21,101 +21,101 @@ def _sum_two(first): return lambda second: first + second -@pytest.mark.parametrize(('iterable', 'sequence'), [ - # Regular types: - - ([], IO(10)), - ([IO(1)], IO(11)), - ([IO(1), IO(2)], IO(13)), - - # Can fail: - - ([], Success(10)), - ([Success(1)], Success(11)), - ([Success(1), Success(2)], Success(13)), - ( - [Failure('a'), Success(1), Success(2)], - Failure('a'), - ), - ([Success(1), Failure('a')], Failure('a')), - ([Failure('a'), Failure('b')], Failure('a')), - - ([], Some(10)), - ([Some(1)], Some(11)), - ([Some(1), Some(2)], Some(13)), - ([Nothing, Some(1), Some(2)], Nothing), - ([Some(1), Nothing, Some(2)], Nothing), - ([Some(1), Some(2), Nothing], Nothing), - ([Nothing], Nothing), - - ([], IOSuccess(10)), - ([IOSuccess(1)], IOSuccess(11)), - ([IOSuccess(1), IOSuccess(2)], IOSuccess(13)), - ( - [IOFailure('a'), IOSuccess(1), IOSuccess(2)], - IOFailure('a'), - ), - ([IOFailure('a'), IOFailure('b')], IOFailure('a')), -]) +@pytest.mark.parametrize( + ('iterable', 'sequence'), + [ + # Regular types: + ([], IO(10)), + ([IO(1)], IO(11)), + ([IO(1), IO(2)], IO(13)), + # Can fail: + ([], Success(10)), + ([Success(1)], Success(11)), + ([Success(1), Success(2)], Success(13)), + ( + [Failure('a'), Success(1), Success(2)], + Failure('a'), + ), + ([Success(1), Failure('a')], Failure('a')), + ([Failure('a'), Failure('b')], Failure('a')), + ([], Some(10)), + ([Some(1)], Some(11)), + ([Some(1), Some(2)], Some(13)), + ([Nothing, Some(1), Some(2)], Nothing), + ([Some(1), Nothing, Some(2)], Nothing), + ([Some(1), Some(2), Nothing], Nothing), + ([Nothing], Nothing), + ([], IOSuccess(10)), + ([IOSuccess(1)], IOSuccess(11)), + ([IOSuccess(1), IOSuccess(2)], IOSuccess(13)), + ( + [IOFailure('a'), IOSuccess(1), IOSuccess(2)], + IOFailure('a'), + ), + ([IOFailure('a'), IOFailure('b')], IOFailure('a')), + ], +) def test_fold_loop(iterable, sequence): """Iterable for ``Result`` and ``FailFast``.""" assert Fold.loop(iterable, sequence.from_value(10), _sum_two) == sequence -@pytest.mark.parametrize(('iterable', 'sequence'), [ - # Regular types: - - ([], Reader.from_value(10)), - ([Reader.from_value(1)], Reader.from_value(11)), - ( - [Reader.from_value(1), Reader.from_value(2)], - Reader.from_value(13), - ), - - # Can fail: - - ([], ReaderResult.from_value(10)), - ([ReaderResult.from_value(1)], ReaderResult.from_value(11)), - ( - [ReaderResult.from_value(1), ReaderResult.from_value(2)], - ReaderResult.from_value(13), - ), - ( - [ +@pytest.mark.parametrize( + ('iterable', 'sequence'), + [ + # Regular types: + ([], Reader.from_value(10)), + ([Reader.from_value(1)], Reader.from_value(11)), + ( + [Reader.from_value(1), Reader.from_value(2)], + Reader.from_value(13), + ), + # Can fail: + ([], ReaderResult.from_value(10)), + ([ReaderResult.from_value(1)], ReaderResult.from_value(11)), + ( + [ReaderResult.from_value(1), ReaderResult.from_value(2)], + ReaderResult.from_value(13), + ), + ( + [ + ReaderResult.from_failure('a'), + ReaderResult.from_value(1), + ReaderResult.from_value(2), + ], + ReaderResult.from_failure('a'), + ), + ( + [ReaderResult.from_failure('a'), ReaderResult.from_failure('b')], ReaderResult.from_failure('a'), - ReaderResult.from_value(1), - ReaderResult.from_value(2), - ], - ReaderResult.from_failure('a'), - ), - ( - [ReaderResult.from_failure('a'), ReaderResult.from_failure('b')], - ReaderResult.from_failure('a'), - ), - - ([], ReaderIOResult.from_value(10)), - ([ReaderIOResult.from_value(1)], ReaderIOResult.from_value(11)), - ( - [ReaderIOResult.from_value(1), ReaderIOResult.from_value(2)], - ReaderIOResult.from_value(13), - ), - ( - [ + ), + ([], ReaderIOResult.from_value(10)), + ([ReaderIOResult.from_value(1)], ReaderIOResult.from_value(11)), + ( + [ReaderIOResult.from_value(1), ReaderIOResult.from_value(2)], + ReaderIOResult.from_value(13), + ), + ( + [ + ReaderIOResult.from_failure('a'), + ReaderIOResult.from_value(1), + ReaderIOResult.from_value(2), + ], + ReaderIOResult.from_failure('a'), + ), + ( + [ + ReaderIOResult.from_failure('a'), + ReaderIOResult.from_failure('b'), + ], + ReaderIOResult.from_failure('a'), + ), + ( + [ReaderIOResult.from_value(1), ReaderIOResult.from_failure('a')], ReaderIOResult.from_failure('a'), - ReaderIOResult.from_value(1), - ReaderIOResult.from_value(2), - ], - ReaderIOResult.from_failure('a'), - ), - ( - [ReaderIOResult.from_failure('a'), ReaderIOResult.from_failure('b')], - ReaderIOResult.from_failure('a'), - ), - ( - [ReaderIOResult.from_value(1), ReaderIOResult.from_failure('a')], - ReaderIOResult.from_failure('a'), - ), -]) + ), + ], +) def test_fold_loop_reader(iterable, sequence): """Ensures that ``.loop`` works for readers.""" assert Fold.loop( @@ -128,10 +128,12 @@ def test_fold_loop_reader(iterable, sequence): @pytest.mark.anyio async def test_fold_loop_reader_future_result(subtests): """Iterable for ``ReaderFutureResult`` and ``Fold``.""" - containers: list[tuple[ # noqa: WPS234 - Iterable[ReaderFutureResult[int, str, NoDeps]], - ReaderFutureResult[int, str, NoDeps], - ]] = [ + containers: list[ + tuple[ # noqa: WPS234 + Iterable[ReaderFutureResult[int, str, NoDeps]], + ReaderFutureResult[int, str, NoDeps], + ] + ] = [ ([], ReaderFutureResult.from_value(10)), ( [ReaderFutureResult.from_value(1)], @@ -170,17 +172,21 @@ async def test_fold_loop_reader_future_result(subtests): for iterable, sequence in containers: with subtests.test(iterable=iterable, sequence=sequence): assert await Fold.loop( - iterable, sequence.from_value(10), _sum_two, + iterable, + sequence.from_value(10), + _sum_two, )(...) == await sequence(...) @pytest.mark.anyio async def test_fold_collect_future(subtests): """Iterable for ``Future`` and ``Fold``.""" - containers: list[tuple[ # noqa: WPS234 - Iterable[Future[int]], - Future[int], - ]] = [ + containers: list[ + tuple[ # noqa: WPS234 + Iterable[Future[int]], + Future[int], + ] + ] = [ ([], Future.from_value(10)), ([Future.from_value(1)], Future.from_value(11)), ( @@ -190,18 +196,25 @@ async def test_fold_collect_future(subtests): ] for iterable, sequence in containers: with subtests.test(iterable=iterable, sequence=sequence): - assert await Fold.loop( - iterable, sequence.from_value(10), _sum_two, - ) == await sequence + assert ( + await Fold.loop( + iterable, + sequence.from_value(10), + _sum_two, + ) + == await sequence + ) @pytest.mark.anyio async def test_fold_collect_future_result(subtests): """Iterable for ``FutureResult`` and ``Fold``.""" - containers: list[tuple[ # noqa: WPS234 - Iterable[FutureResult[int, str]], - FutureResult[int, str], - ]] = [ + containers: list[ + tuple[ # noqa: WPS234 + Iterable[FutureResult[int, str]], + FutureResult[int, str], + ] + ] = [ ([], FutureSuccess(10)), ([FutureSuccess(1)], FutureSuccess(11)), ([FutureSuccess(1), FutureSuccess(2)], FutureSuccess(13)), @@ -214,9 +227,14 @@ async def test_fold_collect_future_result(subtests): ] for iterable, sequence in containers: with subtests.test(iterable=iterable, sequence=sequence): - assert await Fold.loop( - iterable, sequence.from_value(10), _sum_two, - ) == await sequence + assert ( + await Fold.loop( + iterable, + sequence.from_value(10), + _sum_two, + ) + == await sequence + ) def test_fold_loop_recursion_limit(): diff --git a/tests/test_maybe/test_maybe_bind.py b/tests/test_maybe/test_maybe_bind.py index 27516d2e2..2fabdb549 100644 --- a/tests/test_maybe/test_maybe_bind.py +++ b/tests/test_maybe/test_maybe_bind.py @@ -1,9 +1,9 @@ - from returns.maybe import Maybe, Nothing, Some def test_bind_some(): """Ensures that bind works correctly.""" + def factory(inner_value: int) -> Maybe[int]: return Some(inner_value * 2) @@ -16,8 +16,9 @@ def factory(inner_value: int) -> Maybe[int]: def test_bind_optional(): """Ensures that bind_optional works correctly.""" + def factory(inner_value: int) -> int | None: - return inner_value if inner_value else None + return inner_value or None assert Some(1).bind_optional(factory) == Some(1) assert Some(0).bind_optional(factory) == Nothing diff --git a/tests/test_maybe/test_maybe_equality.py b/tests/test_maybe/test_maybe_equality.py index 356600856..0555277f1 100644 --- a/tests/test_maybe/test_maybe_equality.py +++ b/tests/test_maybe/test_maybe_equality.py @@ -2,7 +2,7 @@ import pytest -from returns.maybe import Nothing, Some, _Nothing +from returns.maybe import Nothing, Some, _Nothing # noqa: PLC2701 from returns.primitives.exceptions import ImmutableStateError @@ -23,7 +23,7 @@ def test_not_equals(): def test_equality(): """Ensures that containers can be compared.""" - assert Nothing is Nothing # noqa: WPS312 + assert Nothing is Nothing # noqa: PLR0124, WPS312 assert Nothing == _Nothing() == _Nothing(None) assert Some(5) == Some(5) assert hash(Some(1)) @@ -50,31 +50,31 @@ def test_is_compare(): def test_immutability_failure(): """Ensures that Failure container is immutable.""" with pytest.raises(ImmutableStateError): - Nothing._inner_state = 1 # noqa: WPS437 + Nothing._inner_state = 1 # noqa: SLF001 with pytest.raises(ImmutableStateError): Nothing.missing = 2 with pytest.raises(ImmutableStateError): - del Nothing._inner_state # type: ignore # noqa: WPS420, WPS437 + del Nothing._inner_state # type: ignore # noqa: SLF001, WPS420 with pytest.raises(AttributeError): - Nothing.missing # type: ignore # noqa: WPS428 + Nothing.missing # type: ignore # noqa: B018 def test_immutability_success(): """Ensures that Success container is immutable.""" with pytest.raises(ImmutableStateError): - Some(0)._inner_state = 1 # noqa: WPS437 + Some(0)._inner_state = 1 # noqa: SLF001 with pytest.raises(ImmutableStateError): Some(1).missing = 2 with pytest.raises(ImmutableStateError): - del Some(0)._inner_state # type: ignore # noqa: WPS420, WPS437 + del Some(0)._inner_state # type: ignore # noqa: SLF001, WPS420 with pytest.raises(AttributeError): - Some(1).missing # type: ignore # noqa: WPS428 + Some(1).missing # type: ignore # noqa: B018 def test_success_immutable_copy(): diff --git a/tests/test_maybe/test_maybe_functions/test_maybe_decorator.py b/tests/test_maybe/test_maybe_functions/test_maybe_decorator.py index 2561f7594..77d3a59a5 100644 --- a/tests/test_maybe/test_maybe_functions/test_maybe_decorator.py +++ b/tests/test_maybe/test_maybe_functions/test_maybe_decorator.py @@ -1,10 +1,9 @@ - from returns.maybe import Nothing, Some, maybe @maybe def _function(hashmap: dict[str, str], key: str) -> str | None: - return hashmap.get(key, None) + return hashmap.get(key) def test_maybe_some(): diff --git a/tests/test_maybe/test_nothing_singleton.py b/tests/test_maybe/test_nothing_singleton.py index e28862a91..f7d9e2321 100644 --- a/tests/test_maybe/test_nothing_singleton.py +++ b/tests/test_maybe/test_nothing_singleton.py @@ -1,4 +1,4 @@ -from returns.maybe import _Nothing +from returns.maybe import _Nothing # noqa: PLC2701 def test_nothing_singleton(): diff --git a/tests/test_methods/test_partition.py b/tests/test_methods/test_partition.py index f6ec452f2..8483624d4 100644 --- a/tests/test_methods/test_partition.py +++ b/tests/test_methods/test_partition.py @@ -6,26 +6,29 @@ from returns.result import Failure, Success -@pytest.mark.parametrize(('containers', 'expected'), [ - ( - (Success(1), Success(2), Failure(None), Success(3)), - ([1, 2, 3], [None]), - ), - ( +@pytest.mark.parametrize( + ('containers', 'expected'), + [ ( - IOResult.from_value(1), - IOResult.from_failure(2), - IOResult.from_value(3), - IOResult.from_failure(4), + (Success(1), Success(2), Failure(None), Success(3)), + ([1, 2, 3], [None]), ), - ([IO(1), IO(3)], [IO(2), IO(4)]), - ), - ( - (Some(1), Some(2), Nothing), - ([1, 2], [None]), - ), - ((), ([], [])), -]) + ( + ( + IOResult.from_value(1), + IOResult.from_failure(2), + IOResult.from_value(3), + IOResult.from_failure(4), + ), + ([IO(1), IO(3)], [IO(2), IO(4)]), # noqa: WPS221 + ), + ( + (Some(1), Some(2), Nothing), + ([1, 2], [None]), + ), + ((), ([], [])), + ], +) def test_partition(containers, expected): """Test partition function.""" assert partition(containers) == expected diff --git a/tests/test_pattern_matching.py b/tests/test_pattern_matching.py index 0bf6df60c..e3d48eb2c 100644 --- a/tests/test_pattern_matching.py +++ b/tests/test_pattern_matching.py @@ -5,12 +5,15 @@ from returns.result import Failure, Result, Success -@pytest.mark.parametrize('container', [ - Success(10), - Success(42), - Failure(RuntimeError()), - Failure(Exception()), -]) +@pytest.mark.parametrize( + 'container', + [ + Success(10), + Success(42), + Failure(RuntimeError()), + Failure(Exception()), + ], +) def test_result_pattern_matching(container: Result[int, Exception]): """Ensures ``Result`` containers work properly with pattern matching.""" match container: @@ -31,11 +34,14 @@ def test_result_pattern_matching(container: Result[int, Exception]): pytest.fail('Was not matched') -@pytest.mark.parametrize('container', [ - Some('SOME'), - Some('THERE IS SOME VALUE'), - Nothing, -]) +@pytest.mark.parametrize( + 'container', + [ + Some('SOME'), + Some('THERE IS SOME VALUE'), + Nothing, + ], +) def test_maybe_pattern_matching(container: Maybe[str]): """Ensures ``Maybe`` containers work properly with pattern matching.""" match container: @@ -52,11 +58,14 @@ def test_maybe_pattern_matching(container: Maybe[str]): pytest.fail('Was not matched') -@pytest.mark.parametrize('container', [ - IOSuccess(42.0), - IOSuccess(10.0), - IOFailure(50), -]) +@pytest.mark.parametrize( + 'container', + [ + IOSuccess(42.0), + IOSuccess(10.0), + IOFailure(50), + ], +) def test_ioresult_pattern_matching(container: IOResult[float, int]): """Ensures ``IOResult`` containers work properly with pattern matching.""" match container: diff --git a/tests/test_pipeline/test_is_successful.py b/tests/test_pipeline/test_is_successful.py index 6b4832df9..5357b5c16 100644 --- a/tests/test_pipeline/test_is_successful.py +++ b/tests/test_pipeline/test_is_successful.py @@ -6,17 +6,18 @@ from returns.result import Failure, Success -@pytest.mark.parametrize(('container', 'correct_result'), [ - (Success('a'), True), - (Failure('a'), False), - - (IOSuccess('a'), True), - (IOFailure('a'), False), - - (Some('a'), True), - (Some(None), True), - (Nothing, False), -]) +@pytest.mark.parametrize( + ('container', 'correct_result'), + [ + (Success('a'), True), + (Failure('a'), False), + (IOSuccess('a'), True), + (IOFailure('a'), False), + (Some('a'), True), + (Some(None), True), + (Nothing, False), + ], +) def test_is_successful(container, correct_result): """Ensures that successful state works correctly.""" assert is_successful(container) is correct_result diff --git a/tests/test_pipeline/test_managed/test_managed_future_result.py b/tests/test_pipeline/test_managed/test_managed_future_result.py index e7947f49e..1467acead 100644 --- a/tests/test_pipeline/test_managed/test_managed_future_result.py +++ b/tests/test_pipeline/test_managed/test_managed_future_result.py @@ -1,4 +1,3 @@ - import pytest from returns.future import FutureResult @@ -49,67 +48,69 @@ def __call__( @pytest.mark.anyio -@pytest.mark.parametrize(('acquire', 'use', 'release', 'final_result', 'log'), [ - # Acquire success: - ( - _acquire_success, - _use_success, - _ReleaseSuccess, - IOSuccess('use success'), - [('acquire success', Success('use success'))], - ), - ( - _acquire_success, - _use_success, - _ReleaseFailure, - IOFailure('release failure'), - [], - ), - ( - _acquire_success, - _use_failure, - _ReleaseSuccess, - IOFailure('use failure'), - [('acquire success', Failure('use failure'))], - ), - ( - _acquire_success, - _use_failure, - _ReleaseFailure, - IOFailure('release failure'), - [], - ), - - # Acquire failure: - ( - _acquire_failure, - _use_success, - _ReleaseSuccess, - IOFailure('acquire failure'), - [], - ), - ( - _acquire_failure, - _use_failure, - _ReleaseSuccess, - IOFailure('acquire failure'), - [], - ), - ( - _acquire_failure, - _use_success, - _ReleaseFailure, - IOFailure('acquire failure'), - [], - ), - ( - _acquire_failure, - _use_failure, - _ReleaseFailure, - IOFailure('acquire failure'), - [], - ), -]) +@pytest.mark.parametrize( + ('acquire', 'use', 'release', 'final_result', 'log'), + [ + # Acquire success: + ( + _acquire_success, + _use_success, + _ReleaseSuccess, + IOSuccess('use success'), + [('acquire success', Success('use success'))], + ), + ( + _acquire_success, + _use_success, + _ReleaseFailure, + IOFailure('release failure'), + [], + ), + ( + _acquire_success, + _use_failure, + _ReleaseSuccess, + IOFailure('use failure'), + [('acquire success', Failure('use failure'))], + ), + ( + _acquire_success, + _use_failure, + _ReleaseFailure, + IOFailure('release failure'), + [], + ), + # Acquire failure: + ( + _acquire_failure, + _use_success, + _ReleaseSuccess, + IOFailure('acquire failure'), + [], + ), + ( + _acquire_failure, + _use_failure, + _ReleaseSuccess, + IOFailure('acquire failure'), + [], + ), + ( + _acquire_failure, + _use_success, + _ReleaseFailure, + IOFailure('acquire failure'), + [], + ), + ( + _acquire_failure, + _use_failure, + _ReleaseFailure, + IOFailure('acquire failure'), + [], + ), + ], +) async def test_all_success(acquire, use, release, final_result, log): """Ensures that managed works as intended.""" pipeline_logs: list[tuple[str, Result[str, str]]] = [] diff --git a/tests/test_pipeline/test_managed/test_managed_ioresult.py b/tests/test_pipeline/test_managed/test_managed_ioresult.py index 5281ceac5..decda41f1 100644 --- a/tests/test_pipeline/test_managed/test_managed_ioresult.py +++ b/tests/test_pipeline/test_managed/test_managed_ioresult.py @@ -1,4 +1,3 @@ - import pytest from returns.io import IOFailure, IOResult, IOSuccess @@ -42,67 +41,69 @@ def __call__( return IOFailure('release failure') -@pytest.mark.parametrize(('acquire', 'use', 'release', 'final_result', 'log'), [ - # Acquire success: - ( - _acquire_success, - _use_success, - _ReleaseSuccess, - IOSuccess('use success'), - [('acquire success', Success('use success'))], - ), - ( - _acquire_success, - _use_success, - _ReleaseFailure, - IOFailure('release failure'), - [], - ), - ( - _acquire_success, - _use_failure, - _ReleaseSuccess, - IOFailure('use failure'), - [('acquire success', Failure('use failure'))], - ), - ( - _acquire_success, - _use_failure, - _ReleaseFailure, - IOFailure('release failure'), - [], - ), - - # Acquire failure: - ( - _acquire_failure, - _use_success, - _ReleaseSuccess, - IOFailure('acquire failure'), - [], - ), - ( - _acquire_failure, - _use_failure, - _ReleaseSuccess, - IOFailure('acquire failure'), - [], - ), - ( - _acquire_failure, - _use_success, - _ReleaseFailure, - IOFailure('acquire failure'), - [], - ), - ( - _acquire_failure, - _use_failure, - _ReleaseFailure, - IOFailure('acquire failure'), - [], - ), -]) +@pytest.mark.parametrize( + ('acquire', 'use', 'release', 'final_result', 'log'), + [ + # Acquire success: + ( + _acquire_success, + _use_success, + _ReleaseSuccess, + IOSuccess('use success'), + [('acquire success', Success('use success'))], + ), + ( + _acquire_success, + _use_success, + _ReleaseFailure, + IOFailure('release failure'), + [], + ), + ( + _acquire_success, + _use_failure, + _ReleaseSuccess, + IOFailure('use failure'), + [('acquire success', Failure('use failure'))], + ), + ( + _acquire_success, + _use_failure, + _ReleaseFailure, + IOFailure('release failure'), + [], + ), + # Acquire failure: + ( + _acquire_failure, + _use_success, + _ReleaseSuccess, + IOFailure('acquire failure'), + [], + ), + ( + _acquire_failure, + _use_failure, + _ReleaseSuccess, + IOFailure('acquire failure'), + [], + ), + ( + _acquire_failure, + _use_success, + _ReleaseFailure, + IOFailure('acquire failure'), + [], + ), + ( + _acquire_failure, + _use_failure, + _ReleaseFailure, + IOFailure('acquire failure'), + [], + ), + ], +) def test_all_success(acquire, use, release, final_result, log): """Ensures that managed works as intended.""" pipeline_logs: list[tuple[str, Result[str, str]]] = [] 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 4aa364e43..2db090f05 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 @@ -1,4 +1,3 @@ - import pytest from returns.context import NoDeps, ReaderFutureResult @@ -49,67 +48,69 @@ def __call__( @pytest.mark.anyio -@pytest.mark.parametrize(('acquire', 'use', 'release', 'final_result', 'log'), [ - # Acquire success: - ( - _acquire_success, - _use_success, - _ReleaseSuccess, - IOSuccess('use success'), - [('acquire success', Success('use success'))], - ), - ( - _acquire_success, - _use_success, - _ReleaseFailure, - IOFailure('release failure'), - [], - ), - ( - _acquire_success, - _use_failure, - _ReleaseSuccess, - IOFailure('use failure'), - [('acquire success', Failure('use failure'))], - ), - ( - _acquire_success, - _use_failure, - _ReleaseFailure, - IOFailure('release failure'), - [], - ), - - # Acquire failure: - ( - _acquire_failure, - _use_success, - _ReleaseSuccess, - IOFailure('acquire failure'), - [], - ), - ( - _acquire_failure, - _use_failure, - _ReleaseSuccess, - IOFailure('acquire failure'), - [], - ), - ( - _acquire_failure, - _use_success, - _ReleaseFailure, - IOFailure('acquire failure'), - [], - ), - ( - _acquire_failure, - _use_failure, - _ReleaseFailure, - IOFailure('acquire failure'), - [], - ), -]) +@pytest.mark.parametrize( + ('acquire', 'use', 'release', 'final_result', 'log'), + [ + # Acquire success: + ( + _acquire_success, + _use_success, + _ReleaseSuccess, + IOSuccess('use success'), + [('acquire success', Success('use success'))], + ), + ( + _acquire_success, + _use_success, + _ReleaseFailure, + IOFailure('release failure'), + [], + ), + ( + _acquire_success, + _use_failure, + _ReleaseSuccess, + IOFailure('use failure'), + [('acquire success', Failure('use failure'))], + ), + ( + _acquire_success, + _use_failure, + _ReleaseFailure, + IOFailure('release failure'), + [], + ), + # Acquire failure: + ( + _acquire_failure, + _use_success, + _ReleaseSuccess, + IOFailure('acquire failure'), + [], + ), + ( + _acquire_failure, + _use_failure, + _ReleaseSuccess, + IOFailure('acquire failure'), + [], + ), + ( + _acquire_failure, + _use_success, + _ReleaseFailure, + IOFailure('acquire failure'), + [], + ), + ( + _acquire_failure, + _use_failure, + _ReleaseFailure, + IOFailure('acquire failure'), + [], + ), + ], +) async def test_all_success(acquire, use, release, final_result, log): """Ensures that managed works as intended.""" pipeline_logs: list[tuple[str, Result[str, str]]] = [] 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 82cf6e973..1012358ac 100644 --- a/tests/test_pipeline/test_managed/test_managed_reader_ioresult.py +++ b/tests/test_pipeline/test_managed/test_managed_reader_ioresult.py @@ -1,4 +1,3 @@ - import pytest from returns.context import NoDeps, ReaderIOResult @@ -43,67 +42,69 @@ def __call__( return ReaderIOResult.from_failure('release failure') -@pytest.mark.parametrize(('acquire', 'use', 'release', 'final_result', 'log'), [ - # Acquire success: - ( - _acquire_success, - _use_success, - _ReleaseSuccess, - IOSuccess('use success'), - [('acquire success', Success('use success'))], - ), - ( - _acquire_success, - _use_success, - _ReleaseFailure, - IOFailure('release failure'), - [], - ), - ( - _acquire_success, - _use_failure, - _ReleaseSuccess, - IOFailure('use failure'), - [('acquire success', Failure('use failure'))], - ), - ( - _acquire_success, - _use_failure, - _ReleaseFailure, - IOFailure('release failure'), - [], - ), - - # Acquire failure: - ( - _acquire_failure, - _use_success, - _ReleaseSuccess, - IOFailure('acquire failure'), - [], - ), - ( - _acquire_failure, - _use_failure, - _ReleaseSuccess, - IOFailure('acquire failure'), - [], - ), - ( - _acquire_failure, - _use_success, - _ReleaseFailure, - IOFailure('acquire failure'), - [], - ), - ( - _acquire_failure, - _use_failure, - _ReleaseFailure, - IOFailure('acquire failure'), - [], - ), -]) +@pytest.mark.parametrize( + ('acquire', 'use', 'release', 'final_result', 'log'), + [ + # Acquire success: + ( + _acquire_success, + _use_success, + _ReleaseSuccess, + IOSuccess('use success'), + [('acquire success', Success('use success'))], + ), + ( + _acquire_success, + _use_success, + _ReleaseFailure, + IOFailure('release failure'), + [], + ), + ( + _acquire_success, + _use_failure, + _ReleaseSuccess, + IOFailure('use failure'), + [('acquire success', Failure('use failure'))], + ), + ( + _acquire_success, + _use_failure, + _ReleaseFailure, + IOFailure('release failure'), + [], + ), + # Acquire failure: + ( + _acquire_failure, + _use_success, + _ReleaseSuccess, + IOFailure('acquire failure'), + [], + ), + ( + _acquire_failure, + _use_failure, + _ReleaseSuccess, + IOFailure('acquire failure'), + [], + ), + ( + _acquire_failure, + _use_success, + _ReleaseFailure, + IOFailure('acquire failure'), + [], + ), + ( + _acquire_failure, + _use_failure, + _ReleaseFailure, + IOFailure('acquire failure'), + [], + ), + ], +) def test_all_success(acquire, use, release, final_result, log): """Ensures that managed works as intended.""" pipeline_logs: list[tuple[str, Result[str, str]]] = [] diff --git a/tests/test_primitives/test_asserts/test_assert_equal.py b/tests/test_primitives/test_asserts/test_assert_equal.py index 78af6715a..c92da0bf4 100644 --- a/tests/test_primitives/test_asserts/test_assert_equal.py +++ b/tests/test_primitives/test_asserts/test_assert_equal.py @@ -19,19 +19,15 @@ _containers: Sequence[BaseContainer] = ( Result.from_failure(1), Result.from_value(1), - IO(1), IOResult.from_failure(1), IOResult.from_value(1), - Maybe.from_value(1), Maybe.from_value(None), Maybe.from_optional(None), - Future.from_value(1), FutureResult.from_value(1), FutureResult.from_failure(1), - Reader.from_value(1), ReaderResult.from_value(1), ReaderResult.from_failure(1), diff --git a/tests/test_primitives/test_container/test_base_container/test_pickle.py b/tests/test_primitives/test_container/test_base_container/test_pickle.py index c53aac2fb..f657c2b45 100644 --- a/tests/test_primitives/test_container/test_base_container/test_pickle.py +++ b/tests/test_primitives/test_container/test_base_container/test_pickle.py @@ -11,12 +11,15 @@ class _CustomClass: def __init__(self, inner_value: Any) -> None: self.inner_value = inner_value - def __eq__(self, other: Any) -> bool: - return ( # noqa: E721 - type(other) == type(self) and # noqa: WPS516 - self.inner_value == other.inner_value + def __eq__(self, other: object) -> bool: + return ( + type(other) is type(self) # noqa: WPS516 + and self.inner_value == other.inner_value # type: ignore[attr-defined] ) + def __hash__(self) -> int: + return hash(self.inner_value) + @given( st.one_of( diff --git a/tests/test_primitives/test_container/test_base_container/test_pickle_backward_deserialization.py b/tests/test_primitives/test_container/test_base_container/test_pickle_backward_deserialization.py index d2086f0f8..5b7341c2f 100644 --- a/tests/test_primitives/test_container/test_base_container/test_pickle_backward_deserialization.py +++ b/tests/test_primitives/test_container/test_base_container/test_pickle_backward_deserialization.py @@ -7,8 +7,8 @@ def test_pickle_backward_deserialization(): """Test that BaseContainer can be deserialized from 0.19.0 and earlier.""" # BaseContainer(1) serialized as of 0.19.0 serialized_container = ( - b'\x80\x04\x958\x00\x00\x00\x00\x00\x00\x00\x8c\x1c' + - b'returns.primitives.container\x94\x8c\rBaseContainer' + - b'\x94\x93\x94)\x81\x94K\x01b.' + b'\x80\x04\x958\x00\x00\x00\x00\x00\x00\x00\x8c\x1c' + + b'returns.primitives.container\x94\x8c\rBaseContainer' + + b'\x94\x93\x94)\x81\x94K\x01b.' ) assert pickle.loads(serialized_container) == BaseContainer(1) # noqa: S301 diff --git a/tests/test_primitives/test_laws/test_lawful/test_laws_resolution.py b/tests/test_primitives/test_laws/test_lawful/test_laws_resolution.py index af9e656d9..f48b9792b 100644 --- a/tests/test_primitives/test_laws/test_lawful/test_laws_resolution.py +++ b/tests/test_primitives/test_laws/test_lawful/test_laws_resolution.py @@ -1,4 +1,3 @@ - import pytest from returns.context import ( @@ -14,18 +13,21 @@ from returns.result import Result -@pytest.mark.parametrize('container', [ - Result, - Maybe, - Future, - FutureResult, - IO, - IOResult, - RequiresContext, - RequiresContextFutureResult, - RequiresContextIOResult, - RequiresContextResult, -]) +@pytest.mark.parametrize( + 'container', + [ + Result, + Maybe, + Future, + FutureResult, + IO, + IOResult, + RequiresContext, + RequiresContextFutureResult, + RequiresContextIOResult, + RequiresContextResult, + ], +) def test_laws_resolution(container: type[Lawful]): """Ensures all tests are unique.""" all_laws: list[Law] = [] diff --git a/tests/test_result/test_result_bind.py b/tests/test_result/test_result_bind.py index b7668a65d..ebde55e78 100644 --- a/tests/test_result/test_result_bind.py +++ b/tests/test_result/test_result_bind.py @@ -3,6 +3,7 @@ def test_bind(): """Ensures that bind works.""" + def factory(inner_value: int) -> Result[int, str]: if inner_value > 0: return Success(inner_value * 2) @@ -24,6 +25,7 @@ def factory(inner_value: int) -> Result[int, str]: def test_left_identity_success(): """Ensures that left identity works for Success container.""" + def factory(inner_value: int) -> Result[int, str]: return Success(inner_value * 2) @@ -35,6 +37,7 @@ def factory(inner_value: int) -> Result[int, str]: def test_left_identity_failure(): """Ensures that left identity works for Failure container.""" + def factory(inner_value: int) -> Result[int, int]: return Failure(6) @@ -48,6 +51,7 @@ def factory(inner_value: int) -> Result[int, int]: def test_lash_success(): """Ensures that lash works for Success container.""" + def factory(inner_value) -> Result[int, str]: return Success(inner_value * 2) @@ -60,6 +64,7 @@ def factory(inner_value) -> Result[int, str]: def test_lash_failure(): """Ensures that lash works for Failure container.""" + def factory(inner_value: int) -> Result[str, int]: return Failure(inner_value + 1) diff --git a/tests/test_result/test_result_equality.py b/tests/test_result/test_result_equality.py index 3ae33c63a..b1338b277 100644 --- a/tests/test_result/test_result_equality.py +++ b/tests/test_result/test_result_equality.py @@ -48,31 +48,31 @@ def test_is_compare(): def test_immutability_failure(): """Ensures that Failure container is immutable.""" with pytest.raises(ImmutableStateError): - Failure(0)._inner_state = 1 # noqa: WPS437 + Failure(0)._inner_state = 1 # noqa: SLF001 with pytest.raises(ImmutableStateError): Failure(1).missing = 2 with pytest.raises(ImmutableStateError): - del Failure(0)._inner_state # type: ignore # noqa: WPS420, WPS437 + del Failure(0)._inner_state # type: ignore # noqa: SLF001, WPS420 with pytest.raises(AttributeError): - Failure(1).missing # type: ignore # noqa: WPS428 + Failure(1).missing # type: ignore # noqa: B018 def test_immutability_success(): """Ensures that Success container is immutable.""" with pytest.raises(ImmutableStateError): - Success(0)._inner_state = 1 # noqa: WPS437 + Success(0)._inner_state = 1 # noqa: SLF001 with pytest.raises(ImmutableStateError): Success(1).missing = 2 with pytest.raises(ImmutableStateError): - del Success(0)._inner_state # type: ignore # noqa: WPS420, WPS437 + del Success(0)._inner_state # type: ignore # noqa: SLF001, WPS420 with pytest.raises(AttributeError): - Success(1).missing # type: ignore # noqa: WPS428 + Success(1).missing # type: ignore # noqa: B018 def test_success_immutable_copy(): diff --git a/tests/test_result/test_result_functions/test_safe.py b/tests/test_result/test_result_functions/test_safe.py index 90c972aa8..e582055cf 100644 --- a/tests/test_result/test_result_functions/test_safe.py +++ b/tests/test_result/test_result_functions/test_safe.py @@ -1,4 +1,3 @@ - import pytest from returns.result import Success, safe diff --git a/tests/test_trampolines/test_trampoline_decorator.py b/tests/test_trampolines/test_trampoline_decorator.py index ca64751fc..daf860749 100644 --- a/tests/test_trampolines/test_trampoline_decorator.py +++ b/tests/test_trampolines/test_trampoline_decorator.py @@ -28,18 +28,24 @@ def _with_func_kwarg( return Trampoline(_with_func_kwarg, numbers, func=func + number) -@pytest.mark.parametrize('trampoline_func', [ - _accumulate, - _with_func_kwarg, -]) -@pytest.mark.parametrize('given_range', [ - range(0), - range(1), - range(2), - range(5), - range(sys.getrecursionlimit()), - range(sys.getrecursionlimit() + 1), -]) +@pytest.mark.parametrize( + 'trampoline_func', + [ + _accumulate, + _with_func_kwarg, + ], +) +@pytest.mark.parametrize( + 'given_range', + [ + range(0), + range(1), + range(2), + range(5), + range(sys.getrecursionlimit()), + range(sys.getrecursionlimit() + 1), + ], +) def test_recursion_limit( trampoline_func: Callable[[Iterator[int]], int], given_range: range, diff --git a/typesafety/test_interfaces/test_specific/test_io/test_io_like.yml b/typesafety/test_interfaces/test_specific/test_io/test_io_like.yml index ff59fc28d..285b29c53 100644 --- a/typesafety/test_interfaces/test_specific/test_io/test_io_like.yml +++ b/typesafety/test_interfaces/test_specific/test_io/test_io_like.yml @@ -52,7 +52,7 @@ - case: io_inheritance_wrong - disable_cache: false + disable_cache: true main: | from typing import Callable, TypeVar from returns.interfaces.specific.io import IOLike1 @@ -83,6 +83,7 @@ main:15: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides main:19: error: Signature of "from_io" incompatible with supertype "IOLikeN" [override] main:19: note: Superclass: + main:19: note: @classmethod main:19: note: def [_UpdatedType] from_io(cls, inner_value: IO[_UpdatedType]) -> KindN[MyClass[_ValueType], _UpdatedType, Never, Never] main:19: note: Subclass: main:19: note: def [_NewValueType] from_io(self, inner_value: IO[_NewValueType]) -> MyClass[_NewValueType] diff --git a/typesafety/test_methods/test_partition.yml b/typesafety/test_methods/test_partition.yml index 3f4eeba69..e01940c06 100644 --- a/typesafety/test_methods/test_partition.yml +++ b/typesafety/test_methods/test_partition.yml @@ -29,4 +29,3 @@ x: List[Maybe[int]] reveal_type(partition(x)) # N: Revealed type is "Tuple[builtins.list[builtins.int], builtins.list[None]]" - diff --git a/typesafety/test_primitives/test_tracing/test_collect_traces.yml b/typesafety/test_primitives/test_tracing/test_collect_traces.yml index 2bacedebe..ee0abe43e 100644 --- a/typesafety/test_primitives/test_tracing/test_collect_traces.yml +++ b/typesafety/test_primitives/test_tracing/test_collect_traces.yml @@ -4,7 +4,7 @@ main: | from returns.primitives.tracing import collect_traces - reveal_type(collect_traces) # N: Revealed type is "Overload(def () -> typing.ContextManager[None], def [_FunctionType <: def (*Any, **Any) -> Any] (function: _FunctionType`-1) -> _FunctionType`-1)" + reveal_type(collect_traces) # N: Revealed type is "Overload(def () -> contextlib.AbstractContextManager[None, Union[builtins.bool, None]], def [_FunctionType <: def (*Any, **Any) -> Any] (function: _FunctionType`-1) -> _FunctionType`-1)" - case: collect_traces_context_manager_return_type_two skip: sys.version_info[:2] >= (3, 13) @@ -12,7 +12,7 @@ main: | from returns.primitives.tracing import collect_traces - with reveal_type(collect_traces()): # N: Revealed type is "typing.ContextManager[None]" + with reveal_type(collect_traces()): # N: Revealed type is "contextlib.AbstractContextManager[None, Union[builtins.bool, None]]" pass - case: collect_traces_decorated_function_return_type