Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,22 @@ jobs:
- "3.10"
name: Python ${{ matrix.python }}
steps:
- uses: actions/checkout@v4
- name: Install the latest version of uv and set the python version
uses: astral-sh/setup-uv@v5
- name: Checkout repository
uses: actions/checkout@v5

- name: Install just
uses: extractions/setup-just@v3

- name: Install Python ${{ matrix.python }}
uses: astral-sh/setup-uv@v7
with:
python-version: ${{ matrix.python }}

# Quality
- name: Test with python ${{ matrix.python }}
run: uv run --frozen pytest
run: just test-ci
- name: Lint
run: make lint
- name: Type check
run: make type-check
run: just check

# Packaging
- name: Build packages
Expand Down
32 changes: 32 additions & 0 deletions Justfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
install:
uv sync

build:
uv build

test:
uv run pytest

test-ci:
uv run --frozen pytest

pyright:
uv run pyright

mypy:
uv run mypy

ruff:
uv run ruff check .

[parallel]
check: pyright ruff mypy

fix:
uv run ruff check . --fix
uv run ruff format


[confirm("Are you sure you want to delete all runtime data in var?")]
clean:
git clean var -X --force
20 changes: 0 additions & 20 deletions Makefile

This file was deleted.

6 changes: 4 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ warn_return_any = true
warn_unused_configs = true
warn_unused_ignores = true

[tool.ruff]
target-version = "py310"

[tool.pytest.ini_options]
addopts = ["--tb=short"]
Expand All @@ -68,4 +66,8 @@ dev = [
"pytest-asyncio>=0.25.1",
"pytest-mypy-plugins>=3.2.0",
"ruff>=0.8.6",
"pyright",
]

[tool.pyright]
strict = ["src/result/**"]
14 changes: 7 additions & 7 deletions src/result/result.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def __repr__(self) -> str:
return "Ok({})".format(repr(self._value))

def __eq__(self, other: Any) -> bool:
return isinstance(other, Ok) and self._value == other._value
return isinstance(other, Ok) and self._value == other._value # pyright: ignore[reportUnknownVariableType, reportUnknownMemberType]

def __ne__(self, other: Any) -> bool:
return not (self == other)
Expand Down Expand Up @@ -126,7 +126,7 @@ def unwrap_err(self) -> NoReturn:
"""
raise UnwrapError(self, "Called `Result.unwrap_err()` on an `Ok` value")

def unwrap_or(self, _default: U) -> T:
def unwrap_or(self, _default: U) -> T: # pyright: ignore[reportInvalidTypeVarUse]
"""
Return the value.
"""
Expand Down Expand Up @@ -250,7 +250,7 @@ def __repr__(self) -> str:
return "Err({})".format(repr(self._value))

def __eq__(self, other: Any) -> bool:
return isinstance(other, Err) and self._value == other._value
return isinstance(other, Err) and self._value == other._value # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType]

def __ne__(self, other: Any) -> bool:
return not (self == other)
Expand Down Expand Up @@ -470,7 +470,7 @@ def as_result(
exceptions of the specified exception type(s) are turned into ``Err(exc)``.
"""
if not exceptions or not all(
inspect.isclass(exception) and issubclass(exception, BaseException)
inspect.isclass(exception) and issubclass(exception, BaseException) # pyright: ignore[reportUnnecessaryIsInstance]
for exception in exceptions
):
raise TypeError("as_result() requires one or more exception types")
Expand Down Expand Up @@ -506,7 +506,7 @@ def as_async_result(
exceptions of the specified exception type(s) are turned into ``Err(exc)``.
"""
if not exceptions or not all(
inspect.isclass(exception) and issubclass(exception, BaseException)
inspect.isclass(exception) and issubclass(exception, BaseException) # pyright: ignore[reportUnnecessaryIsInstance]
for exception in exceptions
):
raise TypeError("as_result() requires one or more exception types")
Expand Down Expand Up @@ -542,7 +542,7 @@ def as_generator_result(
Callable[P, Generator[Result[TY, TBE], TS, TR | None]],
]:
if not exceptions or not all(
inspect.isclass(exception) and issubclass(exception, BaseException)
inspect.isclass(exception) and issubclass(exception, BaseException) # pyright: ignore[reportUnnecessaryIsInstance]
for exception in exceptions
):
raise TypeError("as_result() requires one or more exception types")
Expand Down Expand Up @@ -603,7 +603,7 @@ def as_async_generator_result(
Callable[P, AsyncGenerator[Result[TY, TBE], TS]],
]:
if not exceptions or not all(
inspect.isclass(exception) and issubclass(exception, BaseException)
inspect.isclass(exception) and issubclass(exception, BaseException) # pyright: ignore[reportUnnecessaryIsInstance]
for exception in exceptions
):
raise TypeError("as_result() requires one or more exception types")
Expand Down
28 changes: 14 additions & 14 deletions tests/test_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,13 @@ def to_err_lambda(i: int) -> Result[int, int]:

def test_ok_factories() -> None:
instance = Ok(1)
assert instance._value == 1
assert instance._value == 1 # pyright: ignore[reportPrivateUsage]
assert instance.is_ok() is True


def test_err_factories() -> None:
instance = Err(2)
assert instance._value == 2
assert instance._value == 2 # pyright: ignore[reportPrivateUsage]
assert instance.is_err() is True


Expand Down Expand Up @@ -419,13 +419,13 @@ def test_as_result_invalid_usage() -> None:
with pytest.raises(TypeError, match=message):

@as_result() # No exception types specified
def f() -> int:
def f() -> int: # pyright: ignore[reportUnusedFunction]
return 1

with pytest.raises(TypeError, match=message):

@as_result("not an exception type") # type: ignore[arg-type]
def g() -> int:
def g() -> int: # pyright: ignore[reportUnusedFunction]
return 1


Expand Down Expand Up @@ -542,8 +542,8 @@ def test_as_generator_result_with_send() -> None:
@as_generator_result(ValueError)
def my_generator() -> Generator[int, int, None]:
val = yield 1
val = yield val if val is not None else 0
val = yield val + 2 if val is not None else 0
val = yield val if val is not None else 0 # pyright: ignore[reportUnnecessaryComparison]
val = yield val + 2 if val is not None else 0 # pyright: ignore[reportUnnecessaryComparison]

result = my_generator()
assert next(result) == Ok(1)
Expand All @@ -558,13 +558,13 @@ def test_as_generator_result_with_send_and_exception() -> None:
def my_generator() -> Generator[Result[int, ValueError], int, None]:
val: int | None = yield Ok(1)
try:
if val is not None:
if val is not None: # pyright: ignore[reportUnnecessaryComparison]
raise ValueError("Send Value Error")
except ValueError as e:
val = yield Err(e)

val = yield Ok(val) if val is not None else Ok(0)
val = yield Ok(val + 2) if val is not None else Ok(0)
val = yield Ok(val) if val is not None else Ok(0) # pyright: ignore[reportUnnecessaryComparison]
val = yield Ok(val + 2) if val is not None else Ok(0) # pyright: ignore[reportUnnecessaryComparison]

result = my_generator()
assert next(result) == Ok(Ok(1))
Expand Down Expand Up @@ -640,8 +640,8 @@ async def test_as_async_generator_result_with_send() -> None:
@as_async_generator_result(ValueError)
async def my_generator() -> AsyncGenerator[int, int]:
val = yield 1
val = yield val if val is not None else 0
val = yield val + 2 if val is not None else 0
val = yield val if val is not None else 0 # pyright: ignore[reportUnnecessaryComparison]
val = yield val + 2 if val is not None else 0 # pyright: ignore[reportUnnecessaryComparison]

result = my_generator()
assert await anext(result) == Ok(1)
Expand All @@ -657,13 +657,13 @@ async def test_as_async_generator_result_with_send_and_exception() -> None:
async def my_generator() -> AsyncGenerator[Result[int, ValueError], int]:
val: int | None = yield Ok(1)
try:
if val is not None:
if val is not None: # pyright: ignore[reportUnnecessaryComparison]
raise ValueError("Async Send Value Error")
except ValueError as e:
val = yield Err(e)

val = yield Ok(val) if val is not None else Ok(0)
val = yield Ok(val + 2) if val is not None else Ok(0)
val = yield Ok(val) if val is not None else Ok(0) # pyright: ignore[reportUnnecessaryComparison]
val = yield Ok(val + 2) if val is not None else Ok(0) # pyright: ignore[reportUnnecessaryComparison]

result = my_generator()
assert await anext(result) == Ok(Ok(1))
Expand Down
3 changes: 1 addition & 2 deletions tests/test_result_do.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from __future__ import annotations


import pytest

from result import Err, Ok, Result, do, do_async
Expand Down Expand Up @@ -192,7 +191,7 @@ def get_resz(is_suc: bool) -> Result[float, int]:
Ok(len(x) + int(y) + z)
for x in await aget_resx(True)
for y in await aget_resy(True)
for z in get_resz(True)
for z in get_resz(True) # pyright: ignore[reportArgumentType]
)

assert (
Expand Down
24 changes: 24 additions & 0 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.