pythonic-fp-gadgets 4.4.0__tar.gz → 4.6.0__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.
- {pythonic_fp_gadgets-4.4.0 → pythonic_fp_gadgets-4.6.0}/PKG-INFO +1 -1
- {pythonic_fp_gadgets-4.4.0 → pythonic_fp_gadgets-4.6.0}/pyproject.toml +1 -1
- {pythonic_fp_gadgets-4.4.0 → pythonic_fp_gadgets-4.6.0}/src/pythonic_fp/gadgets/__init__.py +23 -18
- {pythonic_fp_gadgets-4.4.0 → pythonic_fp_gadgets-4.6.0}/src/pythonic_fp/gadgets/box.py +4 -7
- {pythonic_fp_gadgets-4.4.0 → pythonic_fp_gadgets-4.6.0}/src/pythonic_fp/gadgets/wrap.py +2 -2
- pythonic_fp_gadgets-4.4.0/src/pythonic_fp/gadgets/sentinels/__init__.pyi +0 -0
- pythonic_fp_gadgets-4.4.0/src/pythonic_fp/gadgets/sentinels/flavored.pyi +0 -8
- pythonic_fp_gadgets-4.4.0/src/pythonic_fp/gadgets/sentinels/novalue.pyi +0 -8
- {pythonic_fp_gadgets-4.4.0 → pythonic_fp_gadgets-4.6.0}/LICENSE +0 -0
- {pythonic_fp_gadgets-4.4.0 → pythonic_fp_gadgets-4.6.0}/README.md +0 -0
- {pythonic_fp_gadgets-4.4.0 → pythonic_fp_gadgets-4.6.0}/src/pythonic_fp/gadgets/py.typed +0 -0
- {pythonic_fp_gadgets-4.4.0 → pythonic_fp_gadgets-4.6.0}/src/pythonic_fp/gadgets/sentinels/__init__.py +0 -0
- {pythonic_fp_gadgets-4.4.0 → pythonic_fp_gadgets-4.6.0}/src/pythonic_fp/gadgets/sentinels/flavored.py +0 -0
- {pythonic_fp_gadgets-4.4.0 → pythonic_fp_gadgets-4.6.0}/src/pythonic_fp/gadgets/sentinels/novalue.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "flit_core.buildapi"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pythonic-fp-gadgets"
|
|
7
|
-
version = "4.
|
|
7
|
+
version = "4.6.0"
|
|
8
8
|
description = "Gadgets without external Pythonic FP dependencies."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.14" # floor: PEP 649/749 deferred annotations — class-level self-reference (SBool in its own ClassVar annotation) NameErrors on <3.14
|
|
@@ -27,7 +27,6 @@ Gadgets
|
|
|
27
27
|
"""
|
|
28
28
|
|
|
29
29
|
from collections.abc import Iterator
|
|
30
|
-
from inspect import getmro
|
|
31
30
|
|
|
32
31
|
__all__ = ['first_common_ancestor', 'iterate_over_arguments']
|
|
33
32
|
|
|
@@ -38,27 +37,33 @@ __license__ = 'Apache License 2.0'
|
|
|
38
37
|
|
|
39
38
|
def first_common_ancestor(cls1: type, cls2: type) -> type:
|
|
40
39
|
"""
|
|
41
|
-
.. admonition::
|
|
40
|
+
.. admonition:: First common ancestor
|
|
42
41
|
|
|
43
|
-
|
|
44
|
-
of two classes.
|
|
42
|
+
Best effort to find the least upper bound in the inheritance
|
|
43
|
+
graph of two classes.
|
|
45
44
|
|
|
46
45
|
:param cls1: A class in the inheritance hierarchy.
|
|
47
46
|
:param cls2: A class in the inheritance hierarchy.
|
|
48
|
-
:returns: First common ancestor
|
|
49
|
-
:raises TypeError:
|
|
50
|
-
|
|
47
|
+
:returns: First common ancestor in ``cls1.__mro__`` order.
|
|
48
|
+
:raises TypeError: Defensively raised when no common ancestor
|
|
49
|
+
is found.
|
|
51
50
|
|
|
52
|
-
..
|
|
51
|
+
.. note::
|
|
52
|
+
|
|
53
|
+
The function is not symmetric in its arguments. In genuine
|
|
54
|
+
multiple inheritance graphs, swapping ``cls1`` and ``cls2``
|
|
55
|
+
can yield a different ancestor. Also, a virtual ancestor
|
|
56
|
+
registered with an ABC may be a tighter bound than anything
|
|
57
|
+
in the actual MRO.
|
|
53
58
|
|
|
54
|
-
|
|
55
|
-
seen are
|
|
59
|
+
.. note::
|
|
56
60
|
|
|
57
|
-
|
|
58
|
-
|
|
61
|
+
Since ``object`` terminates all actual MRO's, ``TypeError``
|
|
62
|
+
is unlikely to ever be thrown, except in the case of some
|
|
63
|
+
exotic metaclass breaking this assumption. This exception
|
|
64
|
+
is here mainly to let typing tools know that object ``None``
|
|
65
|
+
is not a possible return type.
|
|
59
66
|
|
|
60
|
-
This happens frequently when the function is given
|
|
61
|
-
Python builtin types or in multiple inheritance situations.
|
|
62
67
|
|
|
63
68
|
"""
|
|
64
69
|
if issubclass(cls1, cls2):
|
|
@@ -66,10 +71,10 @@ def first_common_ancestor(cls1: type, cls2: type) -> type:
|
|
|
66
71
|
if issubclass(cls2, cls1):
|
|
67
72
|
return cls1
|
|
68
73
|
|
|
69
|
-
for
|
|
70
|
-
if issubclass(
|
|
71
|
-
return
|
|
72
|
-
raise TypeError("
|
|
74
|
+
for ancestor in cls1.__mro__:
|
|
75
|
+
if issubclass(cls2, ancestor):
|
|
76
|
+
return ancestor
|
|
77
|
+
raise TypeError("first_common_ancestor: no common ancestor found!")
|
|
73
78
|
|
|
74
79
|
|
|
75
80
|
def iterate_over_arguments[A](*args: A) -> Iterator[A]:
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
from collections.abc import Callable, Iterator
|
|
16
|
-
from typing import
|
|
16
|
+
from typing import Final, cast, overload
|
|
17
17
|
|
|
18
18
|
__all__ = ['Box']
|
|
19
19
|
|
|
@@ -105,9 +105,7 @@ class Box[T]:
|
|
|
105
105
|
|
|
106
106
|
if self._item is other._item:
|
|
107
107
|
return True
|
|
108
|
-
|
|
109
|
-
return True
|
|
110
|
-
return False
|
|
108
|
+
return self._item == other._item
|
|
111
109
|
|
|
112
110
|
def __repr__(self) -> str:
|
|
113
111
|
"""
|
|
@@ -199,7 +197,6 @@ class Box[T]:
|
|
|
199
197
|
else:
|
|
200
198
|
msg = 'Box: Trying to push an item in a non-empty Box'
|
|
201
199
|
raise ValueError(msg)
|
|
202
|
-
return None
|
|
203
200
|
|
|
204
201
|
def put(self, item: T) -> None:
|
|
205
202
|
"""
|
|
@@ -228,7 +225,7 @@ class Box[T]:
|
|
|
228
225
|
self._item = new_item
|
|
229
226
|
return popped
|
|
230
227
|
|
|
231
|
-
def map[U](self, f: Callable[[T], U]) ->
|
|
228
|
+
def map[U](self, f: Callable[[T], U]) -> Box[U]:
|
|
232
229
|
"""
|
|
233
230
|
.. admonition:: Map
|
|
234
231
|
|
|
@@ -243,7 +240,7 @@ class Box[T]:
|
|
|
243
240
|
return Box()
|
|
244
241
|
return Box(f(cast(T, self._item)))
|
|
245
242
|
|
|
246
|
-
def bind[U](self, f: Callable[[T],
|
|
243
|
+
def bind[U](self, f: Callable[[T], Box[U]]) -> Box[U]:
|
|
247
244
|
"""
|
|
248
245
|
.. admonition:: Bind
|
|
249
246
|
|
|
@@ -147,7 +147,7 @@ class HWrap[T: Hashable](Hashable):
|
|
|
147
147
|
|
|
148
148
|
.. tip::
|
|
149
149
|
|
|
150
|
-
``HWrap`` objects are
|
|
150
|
+
``HWrap`` objects are matchable and hashable.
|
|
151
151
|
|
|
152
152
|
"""
|
|
153
153
|
|
|
@@ -163,7 +163,7 @@ class HWrap[T: Hashable](Hashable):
|
|
|
163
163
|
:param item: Item to be wrapped.
|
|
164
164
|
|
|
165
165
|
"""
|
|
166
|
-
self._item, self._hash = item, hash(item)
|
|
166
|
+
self._item, self._hash = item, hash((item, '_hwrap'))
|
|
167
167
|
|
|
168
168
|
def __hash__(self) -> int:
|
|
169
169
|
return self._hash
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pythonic_fp_gadgets-4.4.0 → pythonic_fp_gadgets-4.6.0}/src/pythonic_fp/gadgets/sentinels/novalue.py
RENAMED
|
File without changes
|