pythonic-fp-gadgets 4.0.0__py3-none-any.whl → 4.0.2__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.
- pythonic_fp/gadgets/__init__.py +28 -26
- pythonic_fp/gadgets/box.py +22 -9
- pythonic_fp/gadgets/sentinels/flavored.py +3 -1
- pythonic_fp/gadgets/sentinels/novalue.py +5 -6
- pythonic_fp/gadgets/wrap.py +21 -1
- {pythonic_fp_gadgets-4.0.0.dist-info → pythonic_fp_gadgets-4.0.2.dist-info}/METADATA +5 -4
- {pythonic_fp_gadgets-4.0.0.dist-info → pythonic_fp_gadgets-4.0.2.dist-info}/RECORD +9 -9
- {pythonic_fp_gadgets-4.0.0.dist-info → pythonic_fp_gadgets-4.0.2.dist-info}/WHEEL +0 -0
- {pythonic_fp_gadgets-4.0.0.dist-info → pythonic_fp_gadgets-4.0.2.dist-info}/licenses/LICENSE +0 -0
pythonic_fp/gadgets/__init__.py
CHANGED
|
@@ -13,44 +13,28 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
"""
|
|
16
|
-
|
|
16
|
+
Gadgets
|
|
17
|
+
-------
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
.. admonition:: Collection of mostly self-contained functions and classes
|
|
20
|
+
|
|
21
|
+
- Functions and classes which could go multiple places or have
|
|
22
|
+
no good place to go.
|
|
23
|
+
- Self-contained with minimal dependencies.
|
|
24
|
+
- No pythonic_fp dependencies.
|
|
24
25
|
|
|
25
26
|
"""
|
|
26
27
|
|
|
27
28
|
from collections.abc import Iterator
|
|
28
29
|
from inspect import getmro
|
|
29
30
|
|
|
30
|
-
__all__ = ['
|
|
31
|
+
__all__ = ['first_common_ancestor', 'iterate_over_arguments']
|
|
31
32
|
|
|
32
33
|
__author__ = 'Geoffrey R. Scheller'
|
|
33
34
|
__copyright__ = 'Copyright (c) 2023-2025 Geoffrey R. Scheller'
|
|
34
35
|
__license__ = 'Apache License 2.0'
|
|
35
36
|
|
|
36
37
|
|
|
37
|
-
def iterate_over_arguments[A](*args: A) -> Iterator[A]:
|
|
38
|
-
"""Function returning an iterator of its arguments.
|
|
39
|
-
|
|
40
|
-
.. note::
|
|
41
|
-
|
|
42
|
-
Does not create an object to iterate over.
|
|
43
|
-
|
|
44
|
-
- well, not in the Python world
|
|
45
|
-
- maybe in the C world
|
|
46
|
-
|
|
47
|
-
:param args: Objects to iterate over.
|
|
48
|
-
:returns: An iterator of the arguments.
|
|
49
|
-
|
|
50
|
-
"""
|
|
51
|
-
yield from args
|
|
52
|
-
|
|
53
|
-
|
|
54
38
|
def first_common_ancestor(cls1: type, cls2: type) -> type:
|
|
55
39
|
"""Find the least upper bound in the inheritance graph
|
|
56
40
|
of two classes.
|
|
@@ -69,7 +53,8 @@ def first_common_ancestor(cls1: type, cls2: type) -> type:
|
|
|
69
53
|
:param cls1: A class in the inheritance hierarchy.
|
|
70
54
|
:param cls2: A class in the inheritance hierarchy.
|
|
71
55
|
:returns: First common ancestor based on getmro order.
|
|
72
|
-
:raises TypeError: Raised
|
|
56
|
+
:raises TypeError: Raised when no common ancestor or not
|
|
57
|
+
caught when raised by ``inspect.getmro``.
|
|
73
58
|
|
|
74
59
|
"""
|
|
75
60
|
if issubclass(cls1, cls2):
|
|
@@ -81,3 +66,20 @@ def first_common_ancestor(cls1: type, cls2: type) -> type:
|
|
|
81
66
|
if issubclass(cls1, common_ancestor) and issubclass(cls2, common_ancestor):
|
|
82
67
|
return common_ancestor
|
|
83
68
|
raise TypeError("latest_common_ancestor: no common ancestor found!!!")
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def iterate_over_arguments[A](*args: A) -> Iterator[A]:
|
|
72
|
+
"""Function returning an iterator of its arguments.
|
|
73
|
+
|
|
74
|
+
.. note::
|
|
75
|
+
|
|
76
|
+
Does not create an object to iterate over.
|
|
77
|
+
|
|
78
|
+
- well, not in the Python world
|
|
79
|
+
- maybe in the C world
|
|
80
|
+
|
|
81
|
+
:param args: Objects to iterate over.
|
|
82
|
+
:returns: An iterator of the functions arguments.
|
|
83
|
+
|
|
84
|
+
"""
|
|
85
|
+
yield from args
|
pythonic_fp/gadgets/box.py
CHANGED
|
@@ -47,7 +47,8 @@ class Box[T]:
|
|
|
47
47
|
|
|
48
48
|
def __init__(self, item: T | _Sentinel = _sentinel) -> None:
|
|
49
49
|
"""
|
|
50
|
-
:param item: An
|
|
50
|
+
:param item: An optional initial contained ``item``
|
|
51
|
+
for the ``Box``.
|
|
51
52
|
"""
|
|
52
53
|
self._item = item
|
|
53
54
|
|
|
@@ -67,6 +68,14 @@ class Box[T]:
|
|
|
67
68
|
return 1 if self else 0
|
|
68
69
|
|
|
69
70
|
def __eq__(self, other: object) -> bool:
|
|
71
|
+
"""
|
|
72
|
+
Efficiently compare to another object.
|
|
73
|
+
|
|
74
|
+
:param other: The object to be compared with,
|
|
75
|
+
:returns: ``True`` if ``other`` is of type Box and contains
|
|
76
|
+
an object which compares as equal to the object
|
|
77
|
+
contained in the ``Box``, otherwise ``False``.
|
|
78
|
+
"""
|
|
70
79
|
if not isinstance(other, type(self)):
|
|
71
80
|
return False
|
|
72
81
|
|
|
@@ -82,11 +91,15 @@ class Box[T]:
|
|
|
82
91
|
def get(self, alt: T) -> T: ...
|
|
83
92
|
|
|
84
93
|
def get(self, alt: T | _Sentinel = _sentinel) -> T:
|
|
85
|
-
"""Return the contained item if it exists, otherwise
|
|
94
|
+
"""Return the contained item, if it exists, otherwise
|
|
95
|
+
an alternate item, if given.
|
|
86
96
|
|
|
87
|
-
:param alt:
|
|
88
|
-
|
|
89
|
-
:
|
|
97
|
+
:param alt: An optional item of type ``T`` to return
|
|
98
|
+
if the ``Box`` is empty.
|
|
99
|
+
:returns: Contents of ``Box`` or an alternate item, if given,
|
|
100
|
+
when the ``Box`` is empty.
|
|
101
|
+
:raises ValueError: When the ``alt`` item is not provided
|
|
102
|
+
but needed.
|
|
90
103
|
|
|
91
104
|
"""
|
|
92
105
|
if self._item is not _sentinel:
|
|
@@ -146,8 +159,8 @@ class Box[T]:
|
|
|
146
159
|
"""Map function ``f`` over contents. We need to return a new
|
|
147
160
|
instance since the type of Box can change.
|
|
148
161
|
|
|
149
|
-
:param f:
|
|
150
|
-
:returns:
|
|
162
|
+
:param f: Mapping function.
|
|
163
|
+
:returns: A new instance.
|
|
151
164
|
|
|
152
165
|
"""
|
|
153
166
|
if self._item is _sentinel:
|
|
@@ -157,8 +170,8 @@ class Box[T]:
|
|
|
157
170
|
def bind[U](self, f: Callable[[T], 'Box[U]']) -> 'Box[U]':
|
|
158
171
|
"""Flatmap ``Box`` with function ``f``.
|
|
159
172
|
|
|
160
|
-
:param f:
|
|
161
|
-
:returns:
|
|
173
|
+
:param f: Binding function.
|
|
174
|
+
:returns: A new instance.
|
|
162
175
|
|
|
163
176
|
"""
|
|
164
177
|
if self._item is _sentinel:
|
|
@@ -13,7 +13,9 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
"""
|
|
16
|
-
|
|
16
|
+
.. admonition:: Sentinel values labeled by different (hashable) flavors.
|
|
17
|
+
|
|
18
|
+
When different flavors of the truth are needed.
|
|
17
19
|
|
|
18
20
|
.. note::
|
|
19
21
|
|
|
@@ -13,9 +13,8 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
"""
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
.. note:
|
|
16
|
+
.. admonition:: Singleton class representing an actually,
|
|
17
|
+
not potentially, missing value.
|
|
19
18
|
|
|
20
19
|
``NoValue()`` is a singleton object representing a missing value.
|
|
21
20
|
|
|
@@ -52,7 +51,7 @@
|
|
|
52
51
|
|
|
53
52
|
Similarly for not equals.
|
|
54
53
|
|
|
55
|
-
.. table:: ``x != y
|
|
54
|
+
.. table:: ``x != y``:wq
|
|
56
55
|
|
|
57
56
|
+-----------+-----------+--------+--------+
|
|
58
57
|
| x∖y | NoValue() | 42 | 57 |
|
|
@@ -113,12 +112,12 @@ class NoValue():
|
|
|
113
112
|
|
|
114
113
|
def __eq__(self, other: object) -> bool:
|
|
115
114
|
"""
|
|
116
|
-
:returns: False
|
|
115
|
+
:returns: ``False``
|
|
117
116
|
"""
|
|
118
117
|
return False
|
|
119
118
|
|
|
120
119
|
def __ne__(self, other: object) -> bool:
|
|
121
120
|
"""
|
|
122
|
-
:returns: False
|
|
121
|
+
:returns: ``False``
|
|
123
122
|
"""
|
|
124
123
|
return False
|
pythonic_fp/gadgets/wrap.py
CHANGED
|
@@ -42,6 +42,14 @@ class Wrap[T]():
|
|
|
42
42
|
return 'Wrap(' + repr(self._item) + ')'
|
|
43
43
|
|
|
44
44
|
def __eq__(self, other: object) -> bool:
|
|
45
|
+
"""
|
|
46
|
+
Efficiently compare to another object.
|
|
47
|
+
|
|
48
|
+
:param other: The object to be compared with,
|
|
49
|
+
:returns: ``True`` if ``other`` is of type Wrap and wraps
|
|
50
|
+
an object which compares as equal to the wrapped
|
|
51
|
+
object, otherwise ``False``.
|
|
52
|
+
"""
|
|
45
53
|
if not isinstance(other, type(self)):
|
|
46
54
|
return False
|
|
47
55
|
|
|
@@ -73,7 +81,11 @@ class HWrap[T: Hashable](Hashable):
|
|
|
73
81
|
|
|
74
82
|
.. tip::
|
|
75
83
|
|
|
76
|
-
``
|
|
84
|
+
``HWrap`` objects can be used in Python match statements.
|
|
85
|
+
|
|
86
|
+
.. tip::
|
|
87
|
+
|
|
88
|
+
``HWrap`` objects are hashable..
|
|
77
89
|
|
|
78
90
|
"""
|
|
79
91
|
__slots__ = ('_item', '_hash')
|
|
@@ -96,6 +108,14 @@ class HWrap[T: Hashable](Hashable):
|
|
|
96
108
|
return 'Wrap(' + repr(self._item) + ')'
|
|
97
109
|
|
|
98
110
|
def __eq__(self, other: object) -> bool:
|
|
111
|
+
"""
|
|
112
|
+
Efficiently compare to another object.
|
|
113
|
+
|
|
114
|
+
:param other: The object to be compared with,
|
|
115
|
+
:returns: ``True`` if ``other`` is of type HWrap and wraps
|
|
116
|
+
an object which compares as equal to the wrapped
|
|
117
|
+
object, otherwise ``False``.
|
|
118
|
+
"""
|
|
99
119
|
if not isinstance(other, type(self)):
|
|
100
120
|
return False
|
|
101
121
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pythonic-fp-gadgets
|
|
3
|
-
Version: 4.0.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 4.0.2
|
|
4
|
+
Summary: Gadgets
|
|
5
5
|
Keywords: gadgets
|
|
6
6
|
Author-email: "Geoffrey R. Scheller" <geoffrey@scheller.com>
|
|
7
7
|
Requires-Python: >=3.13
|
|
@@ -15,7 +15,7 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
15
15
|
Classifier: Typing :: Typed
|
|
16
16
|
License-File: LICENSE
|
|
17
17
|
Requires-Dist: pytest>=8.4.1 ; extra == "test"
|
|
18
|
-
Requires-Dist: pythonic-fp-circulararray>=6.0.
|
|
18
|
+
Requires-Dist: pythonic-fp-circulararray>=6.0.1 ; extra == "test"
|
|
19
19
|
Project-URL: Changelog, https://github.com/grscheller/pythonic-fp-gadgets/blob/main/CHANGELOG.rst
|
|
20
20
|
Project-URL: Documentation, https://grscheller.github.io/pythonic-fp/gadgets/development/build/html/
|
|
21
21
|
Project-URL: Homepage, https://grscheller.github.io/pythonic-fp/homepage/build/html/
|
|
@@ -33,9 +33,10 @@ Library of simple, but useful, classes and functions with no dependencies
|
|
|
33
33
|
outside the Python Standard Library.
|
|
34
34
|
|
|
35
35
|
- Gadgets
|
|
36
|
+
|
|
36
37
|
- single item box
|
|
37
38
|
- function returning iterator of its arguments
|
|
38
|
-
- find the latest common ancestor of two classes
|
|
39
|
+
- function to find the latest common ancestor of two classes
|
|
39
40
|
|
|
40
41
|
Part of the
|
|
41
42
|
`pythonic-fp
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
pythonic_fp/gadgets/__init__.py,sha256=
|
|
1
|
+
pythonic_fp/gadgets/__init__.py,sha256=iEm1j8DIchgQvH4Tom6IyMeYz8i3LSAXBBBtz_gPykE,2673
|
|
2
2
|
pythonic_fp/gadgets/__init__.pyi,sha256=cAf10WX2ZHMs-Tf93mImmDdZw7lNEmwjorkiVF04s_E,224
|
|
3
|
-
pythonic_fp/gadgets/box.py,sha256=
|
|
3
|
+
pythonic_fp/gadgets/box.py,sha256=cmHe2kZhEMNtH51xlpdyd68SV-bBXxC6gRH8N0W6TqE,5443
|
|
4
4
|
pythonic_fp/gadgets/box.pyi,sha256=UkJBY8Xiv4oe70Q3bhJL1jGHwYmFWwkTIdxvf2zR3v4,837
|
|
5
5
|
pythonic_fp/gadgets/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
-
pythonic_fp/gadgets/wrap.py,sha256=
|
|
6
|
+
pythonic_fp/gadgets/wrap.py,sha256=x3mvawiRh9G3vMq3ub5Va6qBJgKcvkCKvWeR6pWrJBw,3929
|
|
7
7
|
pythonic_fp/gadgets/wrap.pyi,sha256=TRbBph_517VNCKchwU-pdtPCn73c09gq8EchDFM7Uyo,868
|
|
8
8
|
pythonic_fp/gadgets/sentinels/__init__.py,sha256=81T-HGQ9BgXj57PO_pduo8MpSQpRgZwT8LIXwODhHkI,724
|
|
9
9
|
pythonic_fp/gadgets/sentinels/__init__.pyi,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
-
pythonic_fp/gadgets/sentinels/flavored.py,sha256=
|
|
10
|
+
pythonic_fp/gadgets/sentinels/flavored.py,sha256=sXgjhBPHEulH9C3Yc09PwAPDscfRH2vKj5JldgS6Sak,2260
|
|
11
11
|
pythonic_fp/gadgets/sentinels/flavored.pyi,sha256=K3YSyXLyylPII2ahRP0olhzLJruOeR73TFJDC6rCUwk,212
|
|
12
|
-
pythonic_fp/gadgets/sentinels/novalue.py,sha256=
|
|
12
|
+
pythonic_fp/gadgets/sentinels/novalue.py,sha256=UbyQ4AVTdM2flLmF2WE0sh7_dErPQiTeM8U6GdWaHN4,3602
|
|
13
13
|
pythonic_fp/gadgets/sentinels/novalue.pyi,sha256=zhZdePpWoQ3ZXOq7xQWGR0A4W_XzasdBQKcoywXZEZI,173
|
|
14
|
-
pythonic_fp_gadgets-4.0.
|
|
15
|
-
pythonic_fp_gadgets-4.0.
|
|
16
|
-
pythonic_fp_gadgets-4.0.
|
|
17
|
-
pythonic_fp_gadgets-4.0.
|
|
14
|
+
pythonic_fp_gadgets-4.0.2.dist-info/licenses/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
|
|
15
|
+
pythonic_fp_gadgets-4.0.2.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
|
|
16
|
+
pythonic_fp_gadgets-4.0.2.dist-info/METADATA,sha256=GsyqIcxiofODEI34GKxzySI-FBv-pkwxaEhnTfZzcOs,1815
|
|
17
|
+
pythonic_fp_gadgets-4.0.2.dist-info/RECORD,,
|
|
File without changes
|
{pythonic_fp_gadgets-4.0.0.dist-info → pythonic_fp_gadgets-4.0.2.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|