pythonic-fp-gadgets 4.0.4__tar.gz → 4.1.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.0.4 → pythonic_fp_gadgets-4.1.0}/.github/workflows/static.yml +2 -2
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/CHANGELOG.rst +10 -3
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/PKG-INFO +2 -2
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/docs/Makefile +2 -2
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/pyproject.toml +2 -2
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/src/pythonic_fp/gadgets/__init__.py +1 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/src/pythonic_fp/gadgets/box.py +43 -27
- pythonic_fp_gadgets-4.1.0/src/pythonic_fp/gadgets/wrap.py +270 -0
- pythonic_fp_gadgets-4.0.4/src/pythonic_fp/gadgets/wrap.py +0 -219
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/.gitignore +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/LICENSE +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/README.rst +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/docs/gen_conf.py +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/docs/requirements.txt +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/docs/source/_static/.gitkeep +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/docs/source/_static/custom.css +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/docs/source/_templates/.gitkeep +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/docs/source/api/box.rst +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/docs/source/api/functions/first_common_ancestor.rst +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/docs/source/api/functions/index.rst +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/docs/source/api/functions/iterate_over_arguments.rst +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/docs/source/api/index.rst +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/docs/source/api/sentinels/flavored.rst +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/docs/source/api/sentinels/index.rst +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/docs/source/api/sentinels/novalue.rst +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/docs/source/api/wrap.rst +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/docs/source/changelog.rst +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/docs/source/description.rst +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/docs/source/index.rst +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/docs/source/releases.rst +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/docs/source/usage.rst +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/src/pythonic_fp/gadgets/__init__.pyi +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/src/pythonic_fp/gadgets/box.pyi +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/src/pythonic_fp/gadgets/py.typed +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/src/pythonic_fp/gadgets/sentinels/__init__.py +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/src/pythonic_fp/gadgets/sentinels/__init__.pyi +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/src/pythonic_fp/gadgets/sentinels/flavored.py +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/src/pythonic_fp/gadgets/sentinels/flavored.pyi +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/src/pythonic_fp/gadgets/sentinels/novalue.py +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/src/pythonic_fp/gadgets/sentinels/novalue.pyi +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/src/pythonic_fp/gadgets/wrap.pyi +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/tests/sentinels/test_novalue.py +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/tests/sentinels/test_sentinel_hidden_implemetation_detail.py +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/tests/sentinels/test_sentinel_with_functions.py +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/tests/test_box.py +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/tests/test_first_common_ancestor.py +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/tests/test_hwrap.py +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/tests/test_iterate_over_arguments.py +0 -0
- {pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/tests/test_wrap.py +0 -0
|
@@ -17,17 +17,24 @@ See `Semantic Versioning 2.0.0 <https://semver.org>`_.
|
|
|
17
17
|
Releases and Important Milestones
|
|
18
18
|
---------------------------------
|
|
19
19
|
|
|
20
|
+
PyPI 4.1.0 - 2026-05-12
|
|
21
|
+
~~~~~~~~~~~~~~~~~~~~~~~
|
|
22
|
+
|
|
23
|
+
- documentation now in maintenance mode
|
|
24
|
+
- development status now "4 - Beta"
|
|
25
|
+
- added a few missing methods
|
|
26
|
+
|
|
20
27
|
PyPI 4.0.4 - 2026-04-26
|
|
21
28
|
~~~~~~~~~~~~~~~~~~~~~~~
|
|
22
29
|
|
|
23
|
-
Much docstring work for sentinels. Need to push now
|
|
24
|
-
|
|
30
|
+
Much docstring work for sentinels. Need to push now to fix
|
|
31
|
+
broken links on PyPI before going into documentation maintenance.
|
|
25
32
|
|
|
26
33
|
Development Status Reappraisal - 2026-05-05
|
|
27
34
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
28
35
|
|
|
29
36
|
Maintainer appraised the Development Status for
|
|
30
|
-
pythonic-fp-gadgets to be
|
|
37
|
+
pythonic-fp-gadgets to be "3 - Alpha".
|
|
31
38
|
|
|
32
39
|
PyPI 4.0.3 - 2026-04-26
|
|
33
40
|
~~~~~~~~~~~~~~~~~~~~~~~
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pythonic-fp-gadgets
|
|
3
|
-
Version: 4.0
|
|
3
|
+
Version: 4.1.0
|
|
4
4
|
Summary: Gadgets
|
|
5
5
|
Keywords: gadgets
|
|
6
6
|
Author-email: "Geoffrey R. Scheller" <geoffrey@scheller.com>
|
|
7
7
|
Requires-Python: >=3.13
|
|
8
8
|
Description-Content-Type: text/x-rst
|
|
9
|
-
Classifier: Development Status ::
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
10
|
Classifier: Framework :: Pytest
|
|
11
11
|
Classifier: Intended Audience :: Developers
|
|
12
12
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
@@ -4,7 +4,7 @@ build-backend = "flit_core.buildapi"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pythonic-fp-gadgets"
|
|
7
|
-
version = "4.0
|
|
7
|
+
version = "4.1.0"
|
|
8
8
|
readme = "README.rst"
|
|
9
9
|
requires-python = ">=3.13"
|
|
10
10
|
authors = [
|
|
@@ -14,7 +14,7 @@ keywords = [
|
|
|
14
14
|
"gadgets",
|
|
15
15
|
]
|
|
16
16
|
classifiers = [
|
|
17
|
-
"Development Status ::
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
18
|
"Framework :: Pytest",
|
|
19
19
|
"Intended Audience :: Developers",
|
|
20
20
|
"License :: OSI Approved :: Apache Software License",
|
|
@@ -52,7 +52,7 @@ class Box[T]:
|
|
|
52
52
|
|
|
53
53
|
Initialize ``Box`` with 0 or 1 items.
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
:param item: An optional initial item for the ``Box``.
|
|
56
56
|
|
|
57
57
|
"""
|
|
58
58
|
self._item = item
|
|
@@ -68,9 +68,9 @@ class Box[T]:
|
|
|
68
68
|
|
|
69
69
|
def __iter__(self) -> Iterator[T]:
|
|
70
70
|
"""
|
|
71
|
-
.. admonition::
|
|
71
|
+
.. admonition:: iter
|
|
72
72
|
|
|
73
|
-
|
|
73
|
+
:yields: Boxed item.
|
|
74
74
|
|
|
75
75
|
"""
|
|
76
76
|
if self:
|
|
@@ -83,7 +83,7 @@ class Box[T]:
|
|
|
83
83
|
- 1 if ``Box`` contains an item
|
|
84
84
|
- 0 if ``Box`` is empty
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
:returns: The number of items currently in the ``Box``.
|
|
87
87
|
|
|
88
88
|
"""
|
|
89
89
|
return 1 if self else 0
|
|
@@ -94,10 +94,10 @@ class Box[T]:
|
|
|
94
94
|
|
|
95
95
|
Efficiently compare ``Box`` to another object.
|
|
96
96
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
97
|
+
:param other: The object to be compared.
|
|
98
|
+
:returns: ``True`` if ``other`` is another ``Box`` containing
|
|
99
|
+
an object which compares as equal to the item
|
|
100
|
+
contained in the ``Box``, otherwise ``False``.
|
|
101
101
|
|
|
102
102
|
"""
|
|
103
103
|
if not isinstance(other, type(self)):
|
|
@@ -111,19 +111,35 @@ class Box[T]:
|
|
|
111
111
|
|
|
112
112
|
def __repr__(self) -> str:
|
|
113
113
|
"""
|
|
114
|
-
.. admonition::
|
|
114
|
+
.. admonition:: repr string
|
|
115
115
|
|
|
116
116
|
Construct string 'Box()' if empty, otherwise 'Box(item_repr)'
|
|
117
117
|
where ``item_repr = repr(item)`` for the currently contained
|
|
118
118
|
item.
|
|
119
119
|
|
|
120
|
-
|
|
120
|
+
:returns: A string to reproduce the current state of the ``Box``.
|
|
121
121
|
|
|
122
122
|
"""
|
|
123
123
|
if self:
|
|
124
124
|
return 'Box(' + repr(self._item) + ')'
|
|
125
125
|
return 'Box()'
|
|
126
126
|
|
|
127
|
+
def __str__(self) -> str:
|
|
128
|
+
"""
|
|
129
|
+
.. admonition:: user string
|
|
130
|
+
|
|
131
|
+
Construct string 'Box()' if empty, otherwise 'Box(item_str)'
|
|
132
|
+
where ``item_str = str(item)`` for the currently contained
|
|
133
|
+
item.
|
|
134
|
+
|
|
135
|
+
:returns: A user meaningful string to represent the current
|
|
136
|
+
state of the ``Box``.
|
|
137
|
+
|
|
138
|
+
"""
|
|
139
|
+
if self:
|
|
140
|
+
return 'Box(' + str(self._item) + ')'
|
|
141
|
+
return 'Box()'
|
|
142
|
+
|
|
127
143
|
@overload
|
|
128
144
|
def get(self) -> T: ...
|
|
129
145
|
@overload
|
|
@@ -136,12 +152,12 @@ class Box[T]:
|
|
|
136
152
|
Return the boxed item, if it exists, otherwise
|
|
137
153
|
an alternate item, if given.
|
|
138
154
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
155
|
+
:param alt: An optional item of type ``T`` to return
|
|
156
|
+
if the ``Box`` is empty.
|
|
157
|
+
:returns: Contents of ``Box`` or an alternate item, if given,
|
|
158
|
+
when the ``Box`` is empty.
|
|
159
|
+
:raises ValueError: When the ``alt`` item is not provided
|
|
160
|
+
but needed.
|
|
145
161
|
|
|
146
162
|
"""
|
|
147
163
|
if self._item is not _sentinel:
|
|
@@ -157,8 +173,8 @@ class Box[T]:
|
|
|
157
173
|
|
|
158
174
|
Pop item from ``Box`` if not empty.
|
|
159
175
|
|
|
160
|
-
|
|
161
|
-
|
|
176
|
+
:returns: The item contained in the ``Box``.
|
|
177
|
+
:raises ValueError: If Box is empty.
|
|
162
178
|
|
|
163
179
|
"""
|
|
164
180
|
if self._item is _sentinel:
|
|
@@ -174,8 +190,8 @@ class Box[T]:
|
|
|
174
190
|
|
|
175
191
|
Push an item into ``Box`` if empty.
|
|
176
192
|
|
|
177
|
-
|
|
178
|
-
|
|
193
|
+
:param item: Item to push into the empty ``Box``.
|
|
194
|
+
:raises ValueError: If ``Box`` is not empty.
|
|
179
195
|
|
|
180
196
|
"""
|
|
181
197
|
if self._item is _sentinel:
|
|
@@ -200,9 +216,9 @@ class Box[T]:
|
|
|
200
216
|
|
|
201
217
|
Exchange an item with what is in the Box.
|
|
202
218
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
219
|
+
:param ``new_item``: New item to exchange for current item.
|
|
220
|
+
:returns: Original contents of the ``Box``.
|
|
221
|
+
:raises ValueError: If Box is empty.
|
|
206
222
|
|
|
207
223
|
"""
|
|
208
224
|
if self._item is _sentinel:
|
|
@@ -219,8 +235,8 @@ class Box[T]:
|
|
|
219
235
|
Map function ``f`` over contents. We need to return a new
|
|
220
236
|
instance since the type of Box can change.
|
|
221
237
|
|
|
222
|
-
|
|
223
|
-
|
|
238
|
+
:param f: Mapping function.
|
|
239
|
+
:returns: New instance.
|
|
224
240
|
|
|
225
241
|
"""
|
|
226
242
|
if self._item is _sentinel:
|
|
@@ -233,8 +249,8 @@ class Box[T]:
|
|
|
233
249
|
|
|
234
250
|
Flatmap ``Box`` with function ``f``.
|
|
235
251
|
|
|
236
|
-
|
|
237
|
-
|
|
252
|
+
:param f: Binding function.
|
|
253
|
+
:returns: New instance.
|
|
238
254
|
|
|
239
255
|
"""
|
|
240
256
|
if self._item is _sentinel:
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
# Copyright 2023-2026 Geoffrey R. Scheller
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
__all__ = ['Wrap', 'HWrap']
|
|
16
|
+
|
|
17
|
+
from collections.abc import Callable, Iterator, Hashable
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class Wrap[T]():
|
|
21
|
+
"""
|
|
22
|
+
.. admonition:: Wrap
|
|
23
|
+
|
|
24
|
+
Immutablely wrap exactly one item.
|
|
25
|
+
|
|
26
|
+
.. tip::
|
|
27
|
+
|
|
28
|
+
``Wrap`` objects are matchable.
|
|
29
|
+
|
|
30
|
+
"""
|
|
31
|
+
__slots__ = ('_item',)
|
|
32
|
+
__match_args__ = ('_item',)
|
|
33
|
+
|
|
34
|
+
def __init__(self, item: T) -> None:
|
|
35
|
+
"""
|
|
36
|
+
.. admonition:: init
|
|
37
|
+
|
|
38
|
+
Initialize ``Wrap`` with 1 required item.
|
|
39
|
+
|
|
40
|
+
:param item: Item to be wrapped.
|
|
41
|
+
|
|
42
|
+
"""
|
|
43
|
+
self._item = item
|
|
44
|
+
|
|
45
|
+
def __bool__(self) -> bool:
|
|
46
|
+
"""
|
|
47
|
+
.. admonition:: bool
|
|
48
|
+
|
|
49
|
+
Truthiness same as wrapped object.
|
|
50
|
+
|
|
51
|
+
"""
|
|
52
|
+
return bool(self._item)
|
|
53
|
+
|
|
54
|
+
def __len__(self) -> int:
|
|
55
|
+
"""
|
|
56
|
+
.. admonition:: len
|
|
57
|
+
|
|
58
|
+
Wrapped items always contain just one item.
|
|
59
|
+
|
|
60
|
+
:returns: 1
|
|
61
|
+
|
|
62
|
+
"""
|
|
63
|
+
return 1
|
|
64
|
+
|
|
65
|
+
def __iter__(self) -> Iterator[T]:
|
|
66
|
+
"""
|
|
67
|
+
.. admonition:: iter
|
|
68
|
+
|
|
69
|
+
:yields: A reference to the wrapped item.
|
|
70
|
+
|
|
71
|
+
"""
|
|
72
|
+
if self:
|
|
73
|
+
yield self._item
|
|
74
|
+
|
|
75
|
+
def __eq__(self, other: object) -> bool:
|
|
76
|
+
"""
|
|
77
|
+
.. admonition:: equality comparison
|
|
78
|
+
|
|
79
|
+
Compare ``Wrap`` to another object.
|
|
80
|
+
|
|
81
|
+
:param other: Object to be compared.
|
|
82
|
+
:returns: ``True`` if ``other`` is of type Wrap and wraps
|
|
83
|
+
an item which compares as equal to the wrapped
|
|
84
|
+
item, otherwise ``False``.
|
|
85
|
+
|
|
86
|
+
"""
|
|
87
|
+
if not isinstance(other, type(self)):
|
|
88
|
+
return False
|
|
89
|
+
|
|
90
|
+
if self._item is other._item:
|
|
91
|
+
return True
|
|
92
|
+
return self._item == other._item
|
|
93
|
+
|
|
94
|
+
def __repr__(self) -> str:
|
|
95
|
+
"""
|
|
96
|
+
.. admonition:: repr string
|
|
97
|
+
|
|
98
|
+
Construct string 'Wrap(item_str)'
|
|
99
|
+
where ``item_str = repr(item)`` for the contained item.
|
|
100
|
+
|
|
101
|
+
:returns: A string to reproduce of the wrapped item.
|
|
102
|
+
|
|
103
|
+
"""
|
|
104
|
+
return 'Wrap(' + repr(self._item) + ')'
|
|
105
|
+
|
|
106
|
+
def __str__(self) -> str:
|
|
107
|
+
"""
|
|
108
|
+
.. admonition:: user string
|
|
109
|
+
|
|
110
|
+
Construct string 'Wrap(item_str)'
|
|
111
|
+
where ``item_str = str(item)`` for the contained item.
|
|
112
|
+
|
|
113
|
+
:returns: A string meaningful to an end user.
|
|
114
|
+
|
|
115
|
+
"""
|
|
116
|
+
return 'Wrap(' + str(self._item) + ')'
|
|
117
|
+
|
|
118
|
+
def map[U](self, f: Callable[[T], U]) -> 'Wrap[U]':
|
|
119
|
+
"""
|
|
120
|
+
.. admonition:: map
|
|
121
|
+
|
|
122
|
+
Map function ``f`` over contents.
|
|
123
|
+
|
|
124
|
+
:param f: Mapping function.
|
|
125
|
+
:returns: New instance.
|
|
126
|
+
|
|
127
|
+
"""
|
|
128
|
+
return Wrap(f(self._item))
|
|
129
|
+
|
|
130
|
+
def bind[U](self, f: Callable[[T], 'Wrap[U]']) -> 'Wrap[U]':
|
|
131
|
+
"""
|
|
132
|
+
.. admonition:: bind
|
|
133
|
+
|
|
134
|
+
Flatmap wrapped object with function ``f``.
|
|
135
|
+
|
|
136
|
+
:param f: Binding function.
|
|
137
|
+
:returns: New instance.
|
|
138
|
+
|
|
139
|
+
"""
|
|
140
|
+
return f(self._item)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class HWrap[T: Hashable](Hashable):
|
|
144
|
+
"""
|
|
145
|
+
.. admonition:: HWrap
|
|
146
|
+
|
|
147
|
+
Immutablely wrap exactly one hashable item.
|
|
148
|
+
|
|
149
|
+
.. tip::
|
|
150
|
+
|
|
151
|
+
``HWrap`` objects are hashable and matchable.
|
|
152
|
+
|
|
153
|
+
"""
|
|
154
|
+
|
|
155
|
+
__slots__ = ('_item', '_hash')
|
|
156
|
+
__match_args__ = ('_item',)
|
|
157
|
+
|
|
158
|
+
def __init__(self, item: T) -> None:
|
|
159
|
+
"""
|
|
160
|
+
.. admonition:: init
|
|
161
|
+
|
|
162
|
+
Initialize ``HWrap`` with 1 required item.
|
|
163
|
+
|
|
164
|
+
:param item: Item to be wrapped.
|
|
165
|
+
|
|
166
|
+
"""
|
|
167
|
+
self._item, self._hash = item, hash(item)
|
|
168
|
+
|
|
169
|
+
def __hash__(self) -> int:
|
|
170
|
+
return self._hash
|
|
171
|
+
|
|
172
|
+
def __bool__(self) -> bool:
|
|
173
|
+
"""
|
|
174
|
+
.. admonition:: bool
|
|
175
|
+
|
|
176
|
+
Truthiness same as wrapped object.
|
|
177
|
+
|
|
178
|
+
"""
|
|
179
|
+
return bool(self._item)
|
|
180
|
+
|
|
181
|
+
def __len__(self) -> int:
|
|
182
|
+
"""
|
|
183
|
+
.. admonition:: len
|
|
184
|
+
|
|
185
|
+
HWrapped items always contain just one item.
|
|
186
|
+
|
|
187
|
+
:returns: 1
|
|
188
|
+
|
|
189
|
+
"""
|
|
190
|
+
return 1
|
|
191
|
+
|
|
192
|
+
def __iter__(self) -> Iterator[T]:
|
|
193
|
+
"""
|
|
194
|
+
.. admonition:: iter
|
|
195
|
+
|
|
196
|
+
:yields: A reference to the wrapped item.
|
|
197
|
+
|
|
198
|
+
"""
|
|
199
|
+
if self:
|
|
200
|
+
yield self._item
|
|
201
|
+
|
|
202
|
+
def __eq__(self, other: object) -> bool:
|
|
203
|
+
"""
|
|
204
|
+
.. admonition:: equality comparison
|
|
205
|
+
|
|
206
|
+
Compare ``HWrap`` to another object.
|
|
207
|
+
|
|
208
|
+
:param other: Object to be compared.
|
|
209
|
+
:returns: ``True`` if ``other`` is of type HWrap and wraps
|
|
210
|
+
an item which compares as equal to the wrapped
|
|
211
|
+
item, otherwise ``False``.
|
|
212
|
+
|
|
213
|
+
"""
|
|
214
|
+
if not isinstance(other, type(self)):
|
|
215
|
+
return False
|
|
216
|
+
|
|
217
|
+
if self._hash != other._hash:
|
|
218
|
+
return False
|
|
219
|
+
if self._item is other._item:
|
|
220
|
+
return True
|
|
221
|
+
return self._item == other._item
|
|
222
|
+
|
|
223
|
+
def __repr__(self) -> str:
|
|
224
|
+
"""
|
|
225
|
+
.. admonition:: repr string
|
|
226
|
+
|
|
227
|
+
Construct string 'HWrap(item_str)'
|
|
228
|
+
where ``item_str = repr(item)`` for the contained item.
|
|
229
|
+
|
|
230
|
+
:returns: A string to reproduce of the wrapped object.
|
|
231
|
+
|
|
232
|
+
"""
|
|
233
|
+
return 'Wrap(' + repr(self._item) + ')'
|
|
234
|
+
|
|
235
|
+
def __str__(self) -> str:
|
|
236
|
+
"""
|
|
237
|
+
.. admonition:: user string
|
|
238
|
+
|
|
239
|
+
Construct string 'HWrap(item_str)'
|
|
240
|
+
where ``item_str = str(item)`` for the contained item.
|
|
241
|
+
|
|
242
|
+
:returns: A string meaningful to an end user.
|
|
243
|
+
|
|
244
|
+
"""
|
|
245
|
+
return 'Wrap(' + str(self._item) + ')'
|
|
246
|
+
|
|
247
|
+
def map[U](self, f: Callable[[T], U]) -> 'HWrap[U]':
|
|
248
|
+
"""
|
|
249
|
+
.. admonition:: map
|
|
250
|
+
|
|
251
|
+
Map function ``f`` over wrapped the wrapped object
|
|
252
|
+
returning a new ``HWrap`` instance.
|
|
253
|
+
|
|
254
|
+
:param f: Mapping function.
|
|
255
|
+
:returns: New instance.
|
|
256
|
+
|
|
257
|
+
"""
|
|
258
|
+
return HWrap(f(self._item))
|
|
259
|
+
|
|
260
|
+
def bind[U](self, f: Callable[[T], 'HWrap[U]']) -> 'HWrap[U]':
|
|
261
|
+
"""
|
|
262
|
+
.. admonition:: bind
|
|
263
|
+
|
|
264
|
+
Flatmap ``Box`` with function ``f``.
|
|
265
|
+
|
|
266
|
+
:param f: Binding function.
|
|
267
|
+
:returns: New instance.
|
|
268
|
+
|
|
269
|
+
"""
|
|
270
|
+
return f(self._item)
|
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
# Copyright 2023-2026 Geoffrey R. Scheller
|
|
2
|
-
#
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
# you may not use this file except in compliance with the License.
|
|
5
|
-
# You may obtain a copy of the License at
|
|
6
|
-
#
|
|
7
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
#
|
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
# See the License for the specific language governing permissions and
|
|
13
|
-
# limitations under the License.
|
|
14
|
-
"""
|
|
15
|
-
.. admonition:: Module wrap
|
|
16
|
-
|
|
17
|
-
Wrap objects in ways to make them "immutable."
|
|
18
|
-
|
|
19
|
-
- Class ``Wrap``: wrap an object
|
|
20
|
-
- Class ``HWrap``: wrap a hashable object
|
|
21
|
-
|
|
22
|
-
"""
|
|
23
|
-
|
|
24
|
-
__all__ = ['Wrap', 'HWrap']
|
|
25
|
-
|
|
26
|
-
from collections.abc import Callable, Iterator, Hashable
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
class Wrap[T]():
|
|
30
|
-
"""
|
|
31
|
-
.. admonition:: Wrap object
|
|
32
|
-
|
|
33
|
-
Immutablely wrap exactly one value of a
|
|
34
|
-
given type. ``Wrap`` objects can be used
|
|
35
|
-
in Python match statements.
|
|
36
|
-
|
|
37
|
-
"""
|
|
38
|
-
__slots__ = ('_item',)
|
|
39
|
-
__match_args__ = ('_item',)
|
|
40
|
-
|
|
41
|
-
def __init__(self, item: T) -> None:
|
|
42
|
-
"""
|
|
43
|
-
.. admonition:: Initializer
|
|
44
|
-
|
|
45
|
-
Initialize ``Wrap`` with 1 required item.
|
|
46
|
-
|
|
47
|
-
:param item: Item to be wrapped.
|
|
48
|
-
|
|
49
|
-
"""
|
|
50
|
-
self._item = item
|
|
51
|
-
|
|
52
|
-
def __bool__(self) -> bool:
|
|
53
|
-
"""
|
|
54
|
-
.. admonition:: Bool
|
|
55
|
-
|
|
56
|
-
Truthiness same as wrapped object.
|
|
57
|
-
|
|
58
|
-
"""
|
|
59
|
-
return bool(self._item)
|
|
60
|
-
|
|
61
|
-
def __iter__(self) -> Iterator[T]:
|
|
62
|
-
"""
|
|
63
|
-
.. admonition:: Iter
|
|
64
|
-
|
|
65
|
-
Iterable, iterates wrapped item.
|
|
66
|
-
|
|
67
|
-
"""
|
|
68
|
-
if self:
|
|
69
|
-
yield self._item
|
|
70
|
-
|
|
71
|
-
def __str__(self) -> str:
|
|
72
|
-
"""
|
|
73
|
-
.. admonition:: User string
|
|
74
|
-
|
|
75
|
-
Construct string 'Box(item_str)'
|
|
76
|
-
where ``item_str = str(item)`` for the currently contained
|
|
77
|
-
item.
|
|
78
|
-
|
|
79
|
-
:returns: A string to reproduce the current state of the ``Box``.
|
|
80
|
-
|
|
81
|
-
"""
|
|
82
|
-
return 'Wrap(' + str(self._item) + ')'
|
|
83
|
-
|
|
84
|
-
def __eq__(self, other: object) -> bool:
|
|
85
|
-
"""
|
|
86
|
-
.. admonition:: Equality comparison
|
|
87
|
-
|
|
88
|
-
Efficiently compare ``Wrap`` to another object.
|
|
89
|
-
|
|
90
|
-
:param other: The object to be compared with,
|
|
91
|
-
:returns: ``True`` if ``other`` is of type Wrap and wraps
|
|
92
|
-
an object which compares as equal to the wrapped
|
|
93
|
-
object, otherwise ``False``.
|
|
94
|
-
|
|
95
|
-
"""
|
|
96
|
-
if not isinstance(other, type(self)):
|
|
97
|
-
return False
|
|
98
|
-
|
|
99
|
-
if self._item is other._item:
|
|
100
|
-
return True
|
|
101
|
-
return self._item == other._item
|
|
102
|
-
|
|
103
|
-
def map[U](self, f: Callable[[T], U]) -> 'Wrap[U]':
|
|
104
|
-
"""
|
|
105
|
-
.. admonition:: Map
|
|
106
|
-
|
|
107
|
-
Map function ``f`` over contents.
|
|
108
|
-
|
|
109
|
-
Map function ``f`` over contents.
|
|
110
|
-
|
|
111
|
-
:param f: Mapping function.
|
|
112
|
-
:returns: New instance.
|
|
113
|
-
|
|
114
|
-
"""
|
|
115
|
-
return Wrap(f(self._item))
|
|
116
|
-
|
|
117
|
-
def bind[U](self, f: Callable[[T], 'Wrap[U]']) -> 'Wrap[U]':
|
|
118
|
-
"""
|
|
119
|
-
.. admonition:: Bind
|
|
120
|
-
|
|
121
|
-
Flatmap wrapped object with function ``f``.
|
|
122
|
-
|
|
123
|
-
:param f: Binding function.
|
|
124
|
-
:returns: New instance.
|
|
125
|
-
|
|
126
|
-
"""
|
|
127
|
-
return f(self._item)
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
class HWrap[T: Hashable](Hashable):
|
|
131
|
-
"""
|
|
132
|
-
.. admonition:: Wrap hashable object
|
|
133
|
-
|
|
134
|
-
Immutablely wrap exactly one value of a
|
|
135
|
-
given hashable type. ``HWrap`` objects can
|
|
136
|
-
be used in Python match statements.
|
|
137
|
-
|
|
138
|
-
.. tip::
|
|
139
|
-
|
|
140
|
-
``HWrap`` objects are hashable.
|
|
141
|
-
|
|
142
|
-
"""
|
|
143
|
-
|
|
144
|
-
__slots__ = ('_item', '_hash')
|
|
145
|
-
__match_args__ = ('_item',)
|
|
146
|
-
|
|
147
|
-
def __init__(self, item: T) -> None:
|
|
148
|
-
self._item, self._hash = item, hash(item)
|
|
149
|
-
|
|
150
|
-
def __hash__(self) -> int:
|
|
151
|
-
return self._hash
|
|
152
|
-
|
|
153
|
-
def __bool__(self) -> bool:
|
|
154
|
-
"""
|
|
155
|
-
.. admonition:: Bool
|
|
156
|
-
|
|
157
|
-
Truthiness same as wrapped object.
|
|
158
|
-
|
|
159
|
-
"""
|
|
160
|
-
return bool(self._item)
|
|
161
|
-
|
|
162
|
-
def __iter__(self) -> Iterator[T]:
|
|
163
|
-
"""
|
|
164
|
-
.. admonition:: Iter
|
|
165
|
-
|
|
166
|
-
Iterable, iterates wrapped item.
|
|
167
|
-
|
|
168
|
-
"""
|
|
169
|
-
if self:
|
|
170
|
-
yield self._item
|
|
171
|
-
|
|
172
|
-
def __repr__(self) -> str:
|
|
173
|
-
return 'Wrap(' + repr(self._item) + ')'
|
|
174
|
-
|
|
175
|
-
def __eq__(self, other: object) -> bool:
|
|
176
|
-
"""
|
|
177
|
-
.. admonition:: Equality comparison
|
|
178
|
-
|
|
179
|
-
Efficiently compare to another object.
|
|
180
|
-
|
|
181
|
-
:param other: Object to be compared
|
|
182
|
-
:returns: ``True`` if ``other`` is of type HWrap and wraps
|
|
183
|
-
an object which compares as equal to the wrapped
|
|
184
|
-
object, otherwise ``False``.
|
|
185
|
-
|
|
186
|
-
"""
|
|
187
|
-
if not isinstance(other, type(self)):
|
|
188
|
-
return False
|
|
189
|
-
|
|
190
|
-
if self._hash != other._hash:
|
|
191
|
-
return False
|
|
192
|
-
if self._item is other._item:
|
|
193
|
-
return True
|
|
194
|
-
return self._item == other._item
|
|
195
|
-
|
|
196
|
-
def map[U](self, f: Callable[[T], U]) -> 'HWrap[U]':
|
|
197
|
-
"""
|
|
198
|
-
.. admonition:: Map
|
|
199
|
-
|
|
200
|
-
Map function ``f`` over wrapped the wrapped object
|
|
201
|
-
returning a new ``HWrap`` instance.
|
|
202
|
-
|
|
203
|
-
:param f: Mapping function.
|
|
204
|
-
:returns: New instance.
|
|
205
|
-
|
|
206
|
-
"""
|
|
207
|
-
return HWrap(f(self._item))
|
|
208
|
-
|
|
209
|
-
def bind[U](self, f: Callable[[T], 'HWrap[U]']) -> 'HWrap[U]':
|
|
210
|
-
"""
|
|
211
|
-
.. admonition:: Bind
|
|
212
|
-
|
|
213
|
-
Flatmap ``Box`` with function ``f``.
|
|
214
|
-
|
|
215
|
-
:param f: Binding function.
|
|
216
|
-
:returns: New instance.
|
|
217
|
-
|
|
218
|
-
"""
|
|
219
|
-
return f(self._item)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/docs/source/api/sentinels/flavored.rst
RENAMED
|
File without changes
|
|
File without changes
|
{pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/docs/source/api/sentinels/novalue.rst
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/src/pythonic_fp/gadgets/__init__.pyi
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/src/pythonic_fp/gadgets/sentinels/novalue.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pythonic_fp_gadgets-4.0.4 → pythonic_fp_gadgets-4.1.0}/tests/test_iterate_over_arguments.py
RENAMED
|
File without changes
|
|
File without changes
|