rust-ok 0.1.0__py3-none-any.whl → 0.2.1__py3-none-any.whl

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.
rust_ok/__init__.py CHANGED
@@ -1,9 +1,13 @@
1
1
  """Public API for rust-ok."""
2
2
 
3
- from .exceptions import IsNotError, RustOkError, UnwrapError
3
+ from importlib.metadata import version
4
+
5
+ __version__ = version("rust_ok")
6
+
4
7
  from .err import Err
5
- from .ok import Ok
8
+ from .exceptions import IsNotError, RustOkError, UnwrapError
6
9
  from .guards import is_err, is_ok
10
+ from .ok import Ok
7
11
  from .result import Result
8
12
  from .trace import format_exception_chain, iter_causes
9
13
 
@@ -18,4 +22,5 @@ __all__ = [
18
22
  "iter_causes",
19
23
  "is_err",
20
24
  "is_ok",
25
+ "__version__",
21
26
  ]
rust_ok/err.py CHANGED
@@ -2,24 +2,31 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import Callable, Optional, TypeVar
5
+ from collections.abc import Callable
6
+ from typing import Any, Never, TypeVar, cast, overload
6
7
 
7
8
  from .exceptions import UnwrapError
8
9
  from .result import Result
9
10
 
10
- T = TypeVar("T")
11
- E = TypeVar("E")
11
+ T_co = TypeVar("T_co", covariant=True)
12
+ E_co = TypeVar("E_co", covariant=True)
12
13
  U = TypeVar("U")
13
14
  F = TypeVar("F")
14
15
 
15
16
 
16
- class Err(Result[T, E]):
17
+ class Err(Result[T_co, E_co]):
17
18
  """Error result containing an error value."""
18
19
 
19
20
  __slots__ = ("_error_value",)
20
21
  __match_args__ = ("error",)
21
22
 
22
- def __init__(self, error: E) -> None:
23
+ @overload
24
+ def __init__(self: Err[Never, E_co], error: E_co) -> None: ...
25
+
26
+ @overload
27
+ def __init__(self: Err[Any, Any], error: Any) -> None: ...
28
+
29
+ def __init__(self, error: E_co | Any) -> None:
23
30
  self._error_value = error
24
31
 
25
32
  def __repr__(self) -> str:
@@ -39,19 +46,19 @@ class Err(Result[T, E]):
39
46
  def __bool__(self) -> bool:
40
47
  return False
41
48
 
42
- def unwrap(self) -> T:
49
+ def unwrap(self) -> T_co:
43
50
  raise UnwrapError(f"Called unwrap on Err: {self._error_value}")
44
51
 
45
- def unwrap_err(self) -> E:
52
+ def unwrap_err(self) -> E_co:
46
53
  return self._error_value
47
54
 
48
- def unwrap_or(self, default: T) -> T:
55
+ def unwrap_or(self, default: T_co | Any) -> T_co:
49
56
  return default
50
57
 
51
- def unwrap_or_else(self, func: Callable[[E], T]) -> T:
58
+ def unwrap_or_else(self, func: Callable[[Any], T_co]) -> T_co:
52
59
  return func(self._error_value)
53
60
 
54
- def expect(self, msg: str) -> T:
61
+ def expect(self, msg: str) -> T_co:
55
62
  raise UnwrapError(f"{msg}: {self._error_value}")
56
63
 
57
64
  def is_ok(self) -> bool:
@@ -60,29 +67,31 @@ class Err(Result[T, E]):
60
67
  def is_err(self) -> bool:
61
68
  return True
62
69
 
63
- def map(self, func: Callable[[T], U]) -> Result[U, E]:
64
- 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))
65
73
 
66
- def map_err(self, func: Callable[[E], F]) -> Result[T, F]:
67
- 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)))
68
76
 
69
- def and_then(self, func: Callable[[T], Result[U, E]]) -> Result[U, E]:
70
- 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))
71
80
 
72
- 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]:
73
82
  return func(self._error_value)
74
83
 
75
- def ok(self) -> T | None:
84
+ def ok(self) -> T_co | None:
76
85
  return None
77
86
 
78
- def err(self) -> E:
87
+ def err(self) -> E_co:
79
88
  return self._error_value
80
89
 
81
90
  def unwrap_or_raise(
82
91
  self,
83
92
  exc_type: type[BaseException] = Exception,
84
- context: Optional[str] = None,
85
- ) -> T:
93
+ context: str | None = None,
94
+ ) -> T_co:
86
95
  payload = self._error_value
87
96
  msg = context if context is not None else str(payload)
88
97
 
rust_ok/ok.py CHANGED
@@ -2,33 +2,37 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import Callable, Literal, Optional, TypeVar, cast, overload
5
+ from collections.abc import Callable
6
+ from typing import Any, Literal, Never, TypeVar, cast, overload
6
7
 
7
8
  from .exceptions import IsNotError, UnwrapError
8
9
  from .result import Result
9
10
 
10
- T = TypeVar("T")
11
- E = TypeVar("E")
11
+ T_co = TypeVar("T_co", covariant=True)
12
+ E_co = TypeVar("E_co", covariant=True)
12
13
  U = TypeVar("U")
13
14
  F = TypeVar("F")
14
15
 
15
16
 
16
- class Ok(Result[T, E]):
17
+ class Ok(Result[T_co, E_co]):
17
18
  """Success result containing a value."""
18
19
 
19
20
  __slots__ = ("value",)
20
21
  __match_args__ = ("value",)
21
22
 
22
- value: T
23
+ value: T_co
23
24
 
24
25
  @overload
25
- def __init__(self: "Ok[None, E]", value: Literal[None] = None) -> None: ...
26
+ def __init__(self: Ok[T_co, Never], value: T_co) -> None: ...
26
27
 
27
28
  @overload
28
- def __init__(self: "Ok[T, E]", value: T) -> None: ...
29
+ def __init__(self: Ok[Any, Any]) -> None: ...
29
30
 
30
- def __init__(self, value: Optional[T] = None) -> None:
31
- self.value = cast(T, value)
31
+ @overload
32
+ def __init__(self: Ok[None, Any], value: Literal[None]) -> None: ...
33
+
34
+ def __init__(self, value: T_co | None = None) -> None:
35
+ self.value = value # type: ignore[assignment]
32
36
 
33
37
  def __repr__(self) -> str:
34
38
  return f"Ok({self.value!r})"
@@ -47,19 +51,20 @@ class Ok(Result[T, E]):
47
51
  def __bool__(self) -> bool:
48
52
  return True
49
53
 
50
- def unwrap(self) -> T:
54
+ def unwrap(self) -> T_co:
51
55
  return self.value
52
56
 
53
- def unwrap_err(self) -> E:
57
+ def unwrap_err(self) -> E_co:
54
58
  raise UnwrapError("Called unwrap_err on Ok")
55
59
 
56
- def unwrap_or(self, default: T) -> T:
60
+ def unwrap_or(self, default: T_co | Any) -> T_co:
57
61
  return self.value
58
62
 
59
- 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."""
60
65
  return self.value
61
66
 
62
- def expect(self, msg: str) -> T:
67
+ def expect(self, msg: str) -> T_co:
63
68
  return self.value
64
69
 
65
70
  def is_ok(self) -> bool:
@@ -68,27 +73,29 @@ class Ok(Result[T, E]):
68
73
  def is_err(self) -> bool:
69
74
  return False
70
75
 
71
- def map(self, func: Callable[[T], U]) -> Result[U, E]:
76
+ def map(self, func: Callable[[Any], U]) -> Result[U, E_co]:
72
77
  return Ok(func(self.value))
73
78
 
74
- def map_err(self, func: Callable[[E], F]) -> Result[T, F]:
75
- return 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))
76
82
 
77
- 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]:
78
84
  return func(self.value)
79
85
 
80
- def or_else(self, func: Callable[[E], Result[T, F]]) -> Result[T, F]:
81
- return 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))
82
89
 
83
- def ok(self) -> T:
90
+ def ok(self) -> T_co:
84
91
  return self.value
85
92
 
86
- def err(self) -> E:
93
+ def err(self) -> E_co:
87
94
  raise IsNotError
88
95
 
89
96
  def unwrap_or_raise(
90
97
  self,
91
98
  exc_type: type[BaseException] = Exception,
92
99
  context: str | None = None,
93
- ) -> T:
100
+ ) -> T_co:
94
101
  return self.value
rust_ok/result.py CHANGED
@@ -2,36 +2,39 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import Callable, Generic, Optional, TypeVar
5
+ from collections.abc import Callable
6
+ from typing import Any, Generic, TypeVar
6
7
 
7
- T = TypeVar("T")
8
- 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
9
12
  U = TypeVar("U")
10
13
  F = TypeVar("F")
11
14
 
12
15
 
13
- class Result(Generic[T, E]):
16
+ class Result(Generic[T_co, E_co]):
14
17
  """Base type for Ok/Err results."""
15
18
 
16
19
  __slots__ = ()
17
20
 
18
- def unwrap(self) -> T:
21
+ def unwrap(self) -> T_co:
19
22
  """Return the contained value if successful, else raise in subclass."""
20
23
  raise NotImplementedError # pragma: no cover
21
24
 
22
- def unwrap_err(self) -> E:
25
+ def unwrap_err(self) -> E_co:
23
26
  """Return the contained error if Err, else raise in subclass."""
24
27
  raise NotImplementedError # pragma: no cover
25
28
 
26
- def unwrap_or(self, default: T) -> T:
29
+ def unwrap_or(self, default: T_co | Any) -> T_co:
27
30
  """Return the contained value if Ok, otherwise return the default."""
28
31
  raise NotImplementedError # pragma: no cover
29
32
 
30
- def unwrap_or_else(self, func: Callable[[E], T]) -> T:
33
+ def unwrap_or_else(self, func: Callable[[Any], T_co]) -> T_co:
31
34
  """Return the contained value if Ok, otherwise compute a default."""
32
35
  raise NotImplementedError # pragma: no cover
33
36
 
34
- def expect(self, msg: str) -> T:
37
+ def expect(self, msg: str) -> T_co:
35
38
  """Return the contained value if Ok, otherwise raise with custom message."""
36
39
  raise NotImplementedError # pragma: no cover
37
40
 
@@ -47,39 +50,39 @@ class Result(Generic[T, E]):
47
50
 
48
51
  return isinstance(self, Err)
49
52
 
50
- def map(self, func: Callable[[T], U]) -> Result[U, E]:
53
+ def map(self, func: Callable[[Any], U]) -> Result[U, E_co]:
51
54
  """Apply func to the contained value if Ok, returning a new Result."""
52
55
  raise NotImplementedError # pragma: no cover
53
56
 
54
- def map_err(self, func: Callable[[E], F]) -> Result[T, F]:
57
+ def map_err(self, func: Callable[[Any], F]) -> Result[T_co, F]:
55
58
  """Apply func to the error if Err, returning a new Result."""
56
59
  raise NotImplementedError # pragma: no cover
57
60
 
58
- 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]:
59
62
  """Chain another computation on the contained value if Ok."""
60
63
  raise NotImplementedError # pragma: no cover
61
64
 
62
- 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]:
63
66
  """Handle the error by calling func if Err, returning a new Result."""
64
67
  raise NotImplementedError # pragma: no cover
65
68
 
66
- def ok(self) -> T | None:
69
+ def ok(self) -> T_co | None:
67
70
  """Return the success value if Ok, otherwise None."""
68
71
  raise NotImplementedError # pragma: no cover
69
72
 
70
- def err(self) -> E:
73
+ def err(self) -> E_co:
71
74
  """Return the error value if Err, otherwise raise in subclass."""
72
75
  raise NotImplementedError # pragma: no cover
73
76
 
74
77
  @property
75
- def error(self) -> E | None:
78
+ def error(self) -> E_co | None:
76
79
  """Return the error value if Err, otherwise None."""
77
80
  return self.err()
78
81
 
79
82
  def unwrap_or_raise(
80
83
  self,
81
84
  exc_type: type[BaseException] = Exception,
82
- context: Optional[str] = None,
83
- ) -> T:
85
+ context: str | None = None,
86
+ ) -> T_co:
84
87
  """Return the Ok value or raise `exc_type`."""
85
88
  raise NotImplementedError # pragma: no cover
rust_ok/trace.py CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ from collections.abc import Iterator
5
6
  from io import StringIO
6
- from typing import Iterator
7
7
 
8
8
 
9
9
  def iter_causes(exc: BaseException) -> Iterator[BaseException]:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: rust-ok
3
- Version: 0.1.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
@@ -33,7 +33,7 @@ License: BSD 3-Clause License
33
33
  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
34
34
  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35
35
  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
- Classifier: Development Status :: 3 - Alpha
36
+ Classifier: Development Status :: 4 - Beta
37
37
  Classifier: Intended Audience :: Developers
38
38
  Classifier: License :: OSI Approved :: BSD License
39
39
  Classifier: Natural Language :: English
@@ -0,0 +1,11 @@
1
+ rust_ok/__init__.py,sha256=bPwWnvWo4gP5YZxYgcTFd5VlYNM1p37-r_32Ge6K6ic,523
2
+ rust_ok/err.py,sha256=LUBoF_OVzzm3Vp9CzyK1ztyrGsVrqp-ZzmFxN_WjXrs,2872
3
+ rust_ok/exceptions.py,sha256=G2FC6K6bBYrbpqUlf7paNp2M0aNWKPC_Onh5toVoOcs,325
4
+ rust_ok/guards.py,sha256=83zQfZPBERs1oO3qrHXrrw74rwKNnp9VQOLTlbjeZbM,496
5
+ rust_ok/ok.py,sha256=MGWZUkzBplrl2lYJ3d5Y8d_XCDI23Si-ZzG7nHe5dbI,2688
6
+ rust_ok/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ rust_ok/result.py,sha256=3F4DIuQzZiM8UB80GkvGXFThgUs0ESe21CCgbRnLDJ8,3183
8
+ rust_ok/trace.py,sha256=yUSTkGC5U6rpFGoe6Yzrs4kN7DEkh5soCFO6JxNZAPw,1218
9
+ rust_ok-0.2.1.dist-info/WHEEL,sha256=XV0cjMrO7zXhVAIyyc8aFf1VjZ33Fen4IiJk5zFlC3g,80
10
+ rust_ok-0.2.1.dist-info/METADATA,sha256=eRW9TT1dR-zYaolo0vlxqHlddPMGbVP9x_r1s1tw3aw,3300
11
+ rust_ok-0.2.1.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: uv 0.9.10
2
+ Generator: uv 0.9.26
3
3
  Root-Is-Purelib: true
4
- Tag: py3-none-any
4
+ Tag: py3-none-any
@@ -1,11 +0,0 @@
1
- rust_ok/__init__.py,sha256=QvHZuMC8oYbIesOeDINf9QkoD-CoQQXS7KFjPs3hIeA,430
2
- rust_ok/err.py,sha256=L7YaUbGJzy7Q1XOKmx1iYGUuwQh1eWADUBhZrke6PDM,2382
3
- rust_ok/exceptions.py,sha256=G2FC6K6bBYrbpqUlf7paNp2M0aNWKPC_Onh5toVoOcs,325
4
- rust_ok/guards.py,sha256=83zQfZPBERs1oO3qrHXrrw74rwKNnp9VQOLTlbjeZbM,496
5
- rust_ok/ok.py,sha256=iHj8dWyoB8J-VRQUpQgLJ8nWsS_xZIVAbnexeCqg8K0,2243
6
- rust_ok/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- rust_ok/result.py,sha256=fdcI3WjXqaeHMEDaOXGCThuwz7SALtJ9aKKDwmg8628,2949
8
- rust_ok/trace.py,sha256=WGuwRHMjCIiXztyLHLUIyNq2DfJbdZ1oW85FrrcZojo,1209
9
- rust_ok-0.1.0.dist-info/WHEEL,sha256=ZHijuPszqKbNczrBXkSuoxdxocbxgFghqnequ9ZQlVk,79
10
- rust_ok-0.1.0.dist-info/METADATA,sha256=rtE8Hk2Zfzq_2I08r2veZlCuVkkul-WsOKgMUyGQSNQ,3301
11
- rust_ok-0.1.0.dist-info/RECORD,,