rust-ok 0.2.0__tar.gz → 0.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: rust-ok
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: Rust-inspired Result/Ok/Err primitives for Python
5
5
  Keywords: result,error-handling,rust,functional,typing
6
6
  Author: pesap
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "rust-ok"
3
- version = "0.2.0"
3
+ version = "0.2.1"
4
4
  description = "Rust-inspired Result/Ok/Err primitives for Python"
5
5
  readme = "README.md"
6
6
  authors = [
@@ -35,11 +35,13 @@ build-backend = "uv_build"
35
35
 
36
36
  [dependency-groups]
37
37
  dev = [
38
+ "mypy>=1.19.1",
38
39
  "pre-commit>=4.5.0,<5.0.0",
40
+ "prek>=0.2.29",
39
41
  "pytest>=8.3.0,<9.0.0",
40
42
  "pytest-cov>=5.0.0,<6.0.0",
41
43
  "ruff>=0.6.8,<0.7.0",
42
- "ty>=0.0.2",
44
+ "ty>=0.0.10",
43
45
  ]
44
46
 
45
47
  [tool.ruff]
@@ -3,31 +3,31 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  from collections.abc import Callable
6
- from typing import Any, TypeVar, cast, overload
6
+ from typing import Any, Never, TypeVar, cast, overload
7
7
 
8
8
  from .exceptions import UnwrapError
9
9
  from .result import Result
10
10
 
11
- T = TypeVar("T")
12
- E = TypeVar("E")
11
+ T_co = TypeVar("T_co", covariant=True)
12
+ E_co = TypeVar("E_co", covariant=True)
13
13
  U = TypeVar("U")
14
14
  F = TypeVar("F")
15
15
 
16
16
 
17
- class Err(Result[T, E]):
17
+ class Err(Result[T_co, E_co]):
18
18
  """Error result containing an error value."""
19
19
 
20
20
  __slots__ = ("_error_value",)
21
21
  __match_args__ = ("error",)
22
22
 
23
23
  @overload
24
- def __init__(self: Err[T, E], error: E) -> None: ...
24
+ def __init__(self: Err[Never, E_co], error: E_co) -> None: ...
25
25
 
26
26
  @overload
27
- def __init__(self: Err[T, Any], error: Any) -> None: ...
27
+ def __init__(self: Err[Any, Any], error: Any) -> None: ...
28
28
 
29
- def __init__(self, error: E | Any) -> None:
30
- self._error_value = cast(E, error)
29
+ def __init__(self, error: E_co | Any) -> None:
30
+ self._error_value = error
31
31
 
32
32
  def __repr__(self) -> str:
33
33
  return f"Err({self._error_value!r})"
@@ -46,19 +46,19 @@ class Err(Result[T, E]):
46
46
  def __bool__(self) -> bool:
47
47
  return False
48
48
 
49
- def unwrap(self) -> T:
49
+ def unwrap(self) -> T_co:
50
50
  raise UnwrapError(f"Called unwrap on Err: {self._error_value}")
51
51
 
52
- def unwrap_err(self) -> E:
52
+ def unwrap_err(self) -> E_co:
53
53
  return self._error_value
54
54
 
55
- def unwrap_or(self, default: T) -> T:
55
+ def unwrap_or(self, default: T_co | Any) -> T_co:
56
56
  return default
57
57
 
58
- def unwrap_or_else(self, func: Callable[[E], T]) -> T:
58
+ def unwrap_or_else(self, func: Callable[[Any], T_co]) -> T_co:
59
59
  return func(self._error_value)
60
60
 
61
- def expect(self, msg: str) -> T:
61
+ def expect(self, msg: str) -> T_co:
62
62
  raise UnwrapError(f"{msg}: {self._error_value}")
63
63
 
64
64
  def is_ok(self) -> bool:
@@ -67,29 +67,31 @@ class Err(Result[T, E]):
67
67
  def is_err(self) -> bool:
68
68
  return True
69
69
 
70
- def map(self, func: Callable[[T], U]) -> Result[U, E]:
71
- return Err(self._error_value)
70
+ def map(self, func: Callable[[Any], U]) -> Result[U, E_co]:
71
+ """Return Err; func is never called."""
72
+ return cast(Result[U, E_co], Err(self._error_value))
72
73
 
73
- def map_err(self, func: Callable[[E], F]) -> Result[T, F]:
74
- return Err(func(self._error_value))
74
+ def map_err(self, func: Callable[[Any], F]) -> Result[T_co, F]:
75
+ return cast(Result[T_co, F], Err(func(self._error_value)))
75
76
 
76
- def and_then(self, func: Callable[[T], Result[U, E]]) -> Result[U, E]:
77
- return Err(self._error_value)
77
+ def and_then(self, func: Callable[[Any], Result[U, E_co]]) -> Result[U, E_co]:
78
+ """Return Err; func is never called."""
79
+ return cast(Result[U, E_co], Err(self._error_value))
78
80
 
79
- def or_else(self, func: Callable[[E], Result[T, F]]) -> Result[T, F]:
81
+ def or_else(self, func: Callable[[Any], Result[T_co, F]]) -> Result[T_co, F]:
80
82
  return func(self._error_value)
81
83
 
82
- def ok(self) -> T | None:
84
+ def ok(self) -> T_co | None:
83
85
  return None
84
86
 
85
- def err(self) -> E:
87
+ def err(self) -> E_co:
86
88
  return self._error_value
87
89
 
88
90
  def unwrap_or_raise(
89
91
  self,
90
92
  exc_type: type[BaseException] = Exception,
91
93
  context: str | None = None,
92
- ) -> T:
94
+ ) -> T_co:
93
95
  payload = self._error_value
94
96
  msg = context if context is not None else str(payload)
95
97
 
@@ -3,36 +3,36 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  from collections.abc import Callable
6
- from typing import Any, Literal, TypeVar, cast, overload
6
+ from typing import Any, Literal, Never, TypeVar, cast, overload
7
7
 
8
8
  from .exceptions import IsNotError, UnwrapError
9
9
  from .result import Result
10
10
 
11
- T = TypeVar("T")
12
- E = TypeVar("E")
11
+ T_co = TypeVar("T_co", covariant=True)
12
+ E_co = TypeVar("E_co", covariant=True)
13
13
  U = TypeVar("U")
14
14
  F = TypeVar("F")
15
15
 
16
16
 
17
- class Ok(Result[T, E]):
17
+ class Ok(Result[T_co, E_co]):
18
18
  """Success result containing a value."""
19
19
 
20
20
  __slots__ = ("value",)
21
21
  __match_args__ = ("value",)
22
22
 
23
- value: T
23
+ value: T_co
24
24
 
25
25
  @overload
26
- def __init__(self: Ok[Any, Any]) -> None: ...
26
+ def __init__(self: Ok[T_co, Never], value: T_co) -> None: ...
27
27
 
28
28
  @overload
29
- def __init__(self: Ok[None, E], value: Literal[None]) -> None: ...
29
+ def __init__(self: Ok[Any, Any]) -> None: ...
30
30
 
31
31
  @overload
32
- def __init__(self: Ok[T, E], value: T) -> None: ...
32
+ def __init__(self: Ok[None, Any], value: Literal[None]) -> None: ...
33
33
 
34
- def __init__(self, value: T | None = None) -> None:
35
- self.value = cast(T, value)
34
+ def __init__(self, value: T_co | None = None) -> None:
35
+ self.value = value # type: ignore[assignment]
36
36
 
37
37
  def __repr__(self) -> str:
38
38
  return f"Ok({self.value!r})"
@@ -51,19 +51,20 @@ class Ok(Result[T, E]):
51
51
  def __bool__(self) -> bool:
52
52
  return True
53
53
 
54
- def unwrap(self) -> T:
54
+ def unwrap(self) -> T_co:
55
55
  return self.value
56
56
 
57
- def unwrap_err(self) -> E:
57
+ def unwrap_err(self) -> E_co:
58
58
  raise UnwrapError("Called unwrap_err on Ok")
59
59
 
60
- def unwrap_or(self, default: T) -> T:
60
+ def unwrap_or(self, default: T_co | Any) -> T_co:
61
61
  return self.value
62
62
 
63
- def unwrap_or_else(self, func: Callable[[E], T]) -> T:
63
+ def unwrap_or_else(self, func: Callable[[Any], T_co]) -> T_co:
64
+ """Return value; func is never called in Ok."""
64
65
  return self.value
65
66
 
66
- def expect(self, msg: str) -> T:
67
+ def expect(self, msg: str) -> T_co:
67
68
  return self.value
68
69
 
69
70
  def is_ok(self) -> bool:
@@ -72,27 +73,29 @@ class Ok(Result[T, E]):
72
73
  def is_err(self) -> bool:
73
74
  return False
74
75
 
75
- def map(self, func: Callable[[T], U]) -> Result[U, E]:
76
+ def map(self, func: Callable[[Any], U]) -> Result[U, E_co]:
76
77
  return Ok(func(self.value))
77
78
 
78
- def map_err(self, func: Callable[[E], F]) -> Result[T, F]:
79
- return cast(Result[T, F], Ok(self.value))
79
+ def map_err(self, func: Callable[[Any], F]) -> Result[T_co, F]:
80
+ """Phantom type: func is never called in Ok."""
81
+ return cast(Result[T_co, F], Ok(self.value))
80
82
 
81
- def and_then(self, func: Callable[[T], Result[U, E]]) -> Result[U, E]:
83
+ def and_then(self, func: Callable[[Any], Result[U, E_co]]) -> Result[U, E_co]:
82
84
  return func(self.value)
83
85
 
84
- def or_else(self, func: Callable[[E], Result[T, F]]) -> Result[T, F]:
85
- return cast(Result[T, F], Ok(self.value))
86
+ def or_else(self, func: Callable[[Any], Result[T_co, F]]) -> Result[T_co, F]:
87
+ """Phantom type: func is never called in Ok."""
88
+ return cast(Result[T_co, F], Ok(self.value))
86
89
 
87
- def ok(self) -> T:
90
+ def ok(self) -> T_co:
88
91
  return self.value
89
92
 
90
- def err(self) -> E:
93
+ def err(self) -> E_co:
91
94
  raise IsNotError
92
95
 
93
96
  def unwrap_or_raise(
94
97
  self,
95
98
  exc_type: type[BaseException] = Exception,
96
99
  context: str | None = None,
97
- ) -> T:
100
+ ) -> T_co:
98
101
  return self.value
@@ -3,36 +3,38 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  from collections.abc import Callable
6
- from typing import Generic, TypeVar
6
+ from typing import Any, Generic, TypeVar
7
7
 
8
- T = TypeVar("T")
9
- E = TypeVar("E")
8
+ # Covariant type variables for Result base type
9
+ T_co = TypeVar("T_co", covariant=True)
10
+ E_co = TypeVar("E_co", covariant=True)
11
+ # TypeVars for transformation method return types
10
12
  U = TypeVar("U")
11
13
  F = TypeVar("F")
12
14
 
13
15
 
14
- class Result(Generic[T, E]):
16
+ class Result(Generic[T_co, E_co]):
15
17
  """Base type for Ok/Err results."""
16
18
 
17
19
  __slots__ = ()
18
20
 
19
- def unwrap(self) -> T:
21
+ def unwrap(self) -> T_co:
20
22
  """Return the contained value if successful, else raise in subclass."""
21
23
  raise NotImplementedError # pragma: no cover
22
24
 
23
- def unwrap_err(self) -> E:
25
+ def unwrap_err(self) -> E_co:
24
26
  """Return the contained error if Err, else raise in subclass."""
25
27
  raise NotImplementedError # pragma: no cover
26
28
 
27
- def unwrap_or(self, default: T) -> T:
29
+ def unwrap_or(self, default: T_co | Any) -> T_co:
28
30
  """Return the contained value if Ok, otherwise return the default."""
29
31
  raise NotImplementedError # pragma: no cover
30
32
 
31
- def unwrap_or_else(self, func: Callable[[E], T]) -> T:
33
+ def unwrap_or_else(self, func: Callable[[Any], T_co]) -> T_co:
32
34
  """Return the contained value if Ok, otherwise compute a default."""
33
35
  raise NotImplementedError # pragma: no cover
34
36
 
35
- def expect(self, msg: str) -> T:
37
+ def expect(self, msg: str) -> T_co:
36
38
  """Return the contained value if Ok, otherwise raise with custom message."""
37
39
  raise NotImplementedError # pragma: no cover
38
40
 
@@ -48,32 +50,32 @@ class Result(Generic[T, E]):
48
50
 
49
51
  return isinstance(self, Err)
50
52
 
51
- def map(self, func: Callable[[T], U]) -> Result[U, E]:
53
+ def map(self, func: Callable[[Any], U]) -> Result[U, E_co]:
52
54
  """Apply func to the contained value if Ok, returning a new Result."""
53
55
  raise NotImplementedError # pragma: no cover
54
56
 
55
- def map_err(self, func: Callable[[E], F]) -> Result[T, F]:
57
+ def map_err(self, func: Callable[[Any], F]) -> Result[T_co, F]:
56
58
  """Apply func to the error if Err, returning a new Result."""
57
59
  raise NotImplementedError # pragma: no cover
58
60
 
59
- def and_then(self, func: Callable[[T], Result[U, E]]) -> Result[U, E]:
61
+ def and_then(self, func: Callable[[Any], Result[U, E_co]]) -> Result[U, E_co]:
60
62
  """Chain another computation on the contained value if Ok."""
61
63
  raise NotImplementedError # pragma: no cover
62
64
 
63
- def or_else(self, func: Callable[[E], Result[T, F]]) -> Result[T, F]:
65
+ def or_else(self, func: Callable[[Any], Result[T_co, F]]) -> Result[T_co, F]:
64
66
  """Handle the error by calling func if Err, returning a new Result."""
65
67
  raise NotImplementedError # pragma: no cover
66
68
 
67
- def ok(self) -> T | None:
69
+ def ok(self) -> T_co | None:
68
70
  """Return the success value if Ok, otherwise None."""
69
71
  raise NotImplementedError # pragma: no cover
70
72
 
71
- def err(self) -> E:
73
+ def err(self) -> E_co:
72
74
  """Return the error value if Err, otherwise raise in subclass."""
73
75
  raise NotImplementedError # pragma: no cover
74
76
 
75
77
  @property
76
- def error(self) -> E | None:
78
+ def error(self) -> E_co | None:
77
79
  """Return the error value if Err, otherwise None."""
78
80
  return self.err()
79
81
 
@@ -81,6 +83,6 @@ class Result(Generic[T, E]):
81
83
  self,
82
84
  exc_type: type[BaseException] = Exception,
83
85
  context: str | None = None,
84
- ) -> T:
86
+ ) -> T_co:
85
87
  """Return the Ok value or raise `exc_type`."""
86
88
  raise NotImplementedError # pragma: no cover
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes