pythonic-fp.iterables 5.1.2__py3-none-any.whl → 5.1.4__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.
@@ -1,4 +1,4 @@
1
- # Copyright 2023-2024 Geoffrey R. Scheller
1
+ # Copyright 2023-2026 Geoffrey R. Scheller
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -13,30 +13,24 @@
13
13
  # limitations under the License.
14
14
 
15
15
  """
16
- Library of functions for iterating iterables
17
- ============================================
16
+ .. admonition:: Composing and iterating iterables
18
17
 
19
- +-----------+-------------------------------------------+
20
- | Module | Description |
21
- +===========+===========================================+
22
- | merging | Concatenating and merging iterables |
23
- +-----------+-------------------------------------------+
24
- | drop_take | Dropping and taking values from iterables |
25
- +-----------+-------------------------------------------+
26
- | folding | Reducing and accumulating iterables |
27
- +-----------+-------------------------------------------+
18
+ - module **merging:** Concatenating and merging iterables.
19
+ - module **drop_take:** Dropping and taking values from iterables.
20
+ - module **folding:** Reducing and accumulating iterables.
28
21
 
29
- Assumptions
30
- -----------
22
+ .. important::
31
23
 
32
- - iterables are not necessarily iterators
33
- - at all times iterator protocol is assumed to be followed
24
+ **Assumptions:**
34
25
 
35
- - all iterators are assumed to be iterable
36
- - for all iterators ``foobar`` we assume ``iter(foobar) is foobar``
26
+ - iterables are not necessarily iterators
27
+ - at all times iterator protocol is assumed to be followed
28
+
29
+ - all iterators are assumed to be iterable
30
+ - for all iterators ``foobar`` we assume ``iter(foobar) is foobar``
37
31
 
38
32
  """
39
33
 
40
34
  __author__ = 'Geoffrey R. Scheller'
41
- __copyright__ = 'Copyright (c) 2023-2025 Geoffrey R. Scheller'
35
+ __copyright__ = 'Copyright (c) 2023-2026 Geoffrey R. Scheller'
42
36
  __license__ = 'Apache License 2.0'
@@ -1,4 +1,4 @@
1
- # Copyright 2023-2025 Geoffrey R. Scheller
1
+ # Copyright 2023-2026 Geoffrey R. Scheller
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -13,7 +13,24 @@
13
13
  # limitations under the License.
14
14
 
15
15
  """
16
- Module pythonic_fp.iterables.drop_take
16
+ .. admonition:: Drop and Take
17
+
18
+ Functions which drop or take items from an iterable.
19
+
20
+ .. important::
21
+
22
+ If iterable is a multiply referenced iterator, items
23
+ dropped or taken need not be the next consecutive items.
24
+
25
+ .. important::
26
+
27
+ If iterable is mutable, iterator may be affected by the
28
+ current state of the original iterable.
29
+
30
+ .. tip::
31
+
32
+ Prefer immutable iterables over mutable ones.
33
+
17
34
  """
18
35
 
19
36
  from collections.abc import Callable, Iterable, Iterator
@@ -30,15 +47,15 @@ __all__ = [
30
47
  ]
31
48
 
32
49
 
33
- ## dropping and taking
34
-
35
-
36
50
  def drop[D](iterable: Iterable[D], n: int) -> Iterator[D]:
37
- """Drop the next n values from iterable.
51
+ """
52
+ .. admonition:: drop
38
53
 
39
- :param iterable: Iterable whose values are to be dropped.
40
- :param n: Number of values to be dropped.
41
- :returns: An iterator of the remaining values.
54
+ Drop the next n items from iterable.
55
+
56
+ :param iterable: Iterable whose items are to be dropped.
57
+ :param n: Number of items to be dropped.
58
+ :yields: The remaining items.
42
59
 
43
60
  """
44
61
  iterator = iter(iterable)
@@ -51,19 +68,22 @@ def drop[D](iterable: Iterable[D], n: int) -> Iterator[D]:
51
68
 
52
69
 
53
70
  def drop_while[D](iterable: Iterable[D], pred: Callable[[D], bool]) -> Iterator[D]:
54
- """Drop initial values from iterable while predicate is true.
71
+ """
72
+ .. admonition:: drop while
73
+
74
+ Drop initial items from iterable while predicate is true.
55
75
 
56
- :param iterable: Iterable whose values are to be dropped.
57
- :param pred: Single argument Boolean valued function, the "predicate".
58
- :returns: An iterator beginning where pred returned false.
76
+ :param iterable: Iterable whose items are to be dropped.
77
+ :param pred: Single argument Boolean items function, the "predicate".
78
+ :yields: items starting when ``pred`` returns ``False``.
59
79
 
60
80
  """
61
81
  iterator = iter(iterable)
62
82
  while True:
63
83
  try:
64
- value = next(iterator)
65
- if not pred(value):
66
- iterator = concat((value,), iterator)
84
+ item = next(iterator)
85
+ if not pred(item):
86
+ iterator = concat((item,), iterator)
67
87
  break
68
88
  except StopIteration:
69
89
  break
@@ -71,40 +91,46 @@ def drop_while[D](iterable: Iterable[D], pred: Callable[[D], bool]) -> Iterator[
71
91
 
72
92
 
73
93
  def take[D](iterable: Iterable[D], n: int) -> Iterator[D]:
74
- """Return an iterator of up to n initial values of an iterable.
94
+ """
95
+ .. admonition:: take
96
+
97
+ Return an iterator yielding up to n items from an iterable.
75
98
 
76
- :param Iterable: iterable providing the values to be taken.
77
- :param n: Number of values to be dropped.
78
- :returns: An iterator of up to n initial values from iterable.
99
+ :param Iterable: Iterable providing the items to be taken.
100
+ :param n: Number of items to be taken.
101
+ :yields: Up to n items from iterable.
79
102
 
80
103
  """
81
104
  iterator = iter(iterable)
82
105
  for _ in range(n):
83
106
  try:
84
- value = next(iterator)
85
- yield value
107
+ item = next(iterator)
108
+ yield item
86
109
  except StopIteration:
87
110
  break
88
111
 
89
112
 
90
113
  def take_while[D](iterable: Iterable[D], pred: Callable[[D], bool]) -> Iterator[D]:
91
- """Yield values from iterable while predicate is true.
114
+ """
115
+ .. admonition:: take while
92
116
 
93
- .. warning::
117
+ Return an iterator of items until predicate false.
94
118
 
95
- Risk of value loss if iterable is multiple referenced iterator.
119
+ :param iterable: Iterable providing the items to be taken.
120
+ :param pred: Single argument Boolean valued function, the "predicate".
121
+ :yields: Items from iterable while predicate is true.
96
122
 
97
- :param iterable: Iterable providing the values to be taken.
98
- :param pred: Single argument Boolean valued function, the "predicate".
99
- :returns: An Iterator of of values from iterable until predicate false.
123
+ .. warning::
124
+
125
+ Risk of data loss if iterable is multiple referenced iterator.
100
126
 
101
127
  """
102
128
  iterator = iter(iterable)
103
129
  while True:
104
130
  try:
105
- value = next(iterator)
106
- if pred(value):
107
- yield value
131
+ item = next(iterator)
132
+ if pred(item):
133
+ yield item
108
134
  else:
109
135
  break
110
136
  except StopIteration:
@@ -112,16 +138,21 @@ def take_while[D](iterable: Iterable[D], pred: Callable[[D], bool]) -> Iterator[
112
138
 
113
139
 
114
140
  def take_split[D](iterable: Iterable[D], n: int) -> tuple[Iterator[D], Iterator[D]]:
115
- """Same as take except also return iterator of remaining values.
141
+ """
142
+ .. admonition:: take split
143
+
144
+ Same as take except also return an iterator of
145
+ the remaining items.
116
146
 
117
- .. Warning::
147
+ .. admonition:: CONTRACT
118
148
 
119
- **CONTRACT:** Do not access the second returned iterator until the
120
- first one is exhausted.
149
+ **CONTRACT:** Do not access the second iterator until
150
+ the first one is completely exhausted.
121
151
 
122
- :param iterable: Iterable providing the values to be taken.
123
- :param n: maximum Number of values to be taken.
124
- :returns: An iterator of values taken and an iterator of remaining values.
152
+ :param iterable: Iterable providing the items to be taken.
153
+ :param n: maximum Number of items to be taken.
154
+ :returns: A tuple containing an iterator of items taken
155
+ and an iterator of remaining items.
125
156
 
126
157
  """
127
158
  iterator = iter(iterable)
@@ -133,16 +164,21 @@ def take_split[D](iterable: Iterable[D], n: int) -> tuple[Iterator[D], Iterator[
133
164
  def take_while_split[D](
134
165
  iterable: Iterable[D], pred: Callable[[D], bool]
135
166
  ) -> tuple[Iterator[D], Iterator[D]]:
136
- """Yield values from iterable while predicate is true.
167
+ """
168
+ .. admonition:: take while
169
+
170
+ Same as take_while except also return an iterator of
171
+ the remaining items.
137
172
 
138
- .. Warning::
173
+ .. admonition:: CONTRACT
139
174
 
140
- **CONTRACT:** Do not access the second returned iterator until
141
- the first one is exhausted.
175
+ **CONTRACT:** Do not access the second iterator until
176
+ the first one is completely exhausted.
142
177
 
143
- :param iterable: Iterable providing the values to be taken.
144
- :param pred: Single argument Boolean valued function.
145
- :returns: Tuple of iterator of values taken and an iterator of remaining values.
178
+ :param iterable: Iterable providing the items to be taken.
179
+ :param pred: Single argument Boolean valued function.
180
+ :returns: A tuple containing an iterator of items taken while
181
+ ``pred`` truthy and an iterator of remaining items.
146
182
 
147
183
  """
148
184
 
@@ -160,7 +196,7 @@ def take_while_split[D](
160
196
  break
161
197
 
162
198
  iterator = iter(iterable)
163
- value: Box[D] = Box()
164
- it_pred = _take_while(iterator, pred, value)
199
+ item: Box[D] = Box()
200
+ it_pred = _take_while(iterator, pred, item)
165
201
 
166
- return (it_pred, concat(value, iterator))
202
+ return it_pred, concat(item, iterator)
@@ -1,4 +1,4 @@
1
- # Copyright 2023-2025 Geoffrey R. Scheller
1
+ # Copyright 2023-2026 Geoffrey R. Scheller
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -12,7 +12,12 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- """Module pythonic_fp.iterables.folding"""
15
+ """
16
+ .. admonition:: Folding and Accumulating
17
+
18
+ Functions to reduce and accumulate items from iterables.
19
+
20
+ """
16
21
 
17
22
  from collections.abc import Callable, Iterable, Iterator
18
23
  from typing import cast, Never
@@ -34,17 +39,24 @@ __all__ = [
34
39
  def accumulate[D, L](
35
40
  iterable: Iterable[D], f: Callable[[L, D], L], initial: L | NoValue = NoValue()
36
41
  ) -> Iterator[L]:
37
- """Returns an iterator of partial fold values.
42
+ """
43
+ .. admonition:: accumulate
44
+
45
+ Returns an iterator of partial fold items. A pure Python
46
+ version of
47
+
48
+ :param iterable: Iterable to be folded.
49
+ :param f: Two parameter function, first parameter for accumulated items.
50
+ :param initial: Optional ``initial`` item to start fold.
51
+ :yields: The intermediate folded items.
38
52
 
39
- A pure Python version of standard library's ``itertools.accumulate``
53
+ .. note::
40
54
 
41
- - function ``f`` does not default to addition (for typing flexibility)
42
- - begins accumulation with an "optional" ``initial`` value
55
+ A pure Python implementation of the standard
56
+ library's ``itertools.accumulate``
43
57
 
44
- :param iterable: iterable to be folded
45
- :param f: two parameter function, first parameter for accumulated value
46
- :param initial: "optional" initial value to start fold
47
- :return: an iterator of the intermediate fold values
58
+ - function ``f`` does not default to addition (for typing flexibility)
59
+ - begins accumulation with an optional ``initial`` item
48
60
 
49
61
  """
50
62
  it = iter(iterable)
@@ -72,21 +84,21 @@ def accumulate[D, L](
72
84
 
73
85
 
74
86
  def reduce_left[D](iterable: Iterable[D], f: Callable[[D, D], D]) -> D | Never:
75
- """Fold an iterable left with a function.
76
-
77
- .. Warning::
87
+ """
88
+ .. admonition:: reduce left
78
89
 
79
- This function never return if given an infinite iterable.
90
+ Fold an iterable left with a function.
80
91
 
81
- .. Warning::
92
+ :param iterable: Iterable to be reduced (folded).
93
+ :param f: Two parameter function, first parameter for accumulated items.
94
+ :return: Reduced item from the iterable.
95
+ :raises StopIteration: When called on an empty iterable.
96
+ :raises Exception: Does not catch any exceptions from ``f``.
82
97
 
83
- This function does not catch or re-raises exceptions from ``f``.
98
+ .. warning::
84
99
 
85
- :param iterable: iterable to be reduced (folded)
86
- :param f: two parameter function, first parameter for accumulated value
87
- :return: reduced value from the iterable
88
- :raises StopIteration: when called on an empty iterable
89
- :raises Exception: does not catch any exceptions from ``f``
100
+ - never returns if given an infinite iterable
101
+ - does not catch or re-raises exceptions raised by ``f``
90
102
 
91
103
  """
92
104
  it = iter(iterable)
@@ -105,24 +117,24 @@ def reduce_left[D](iterable: Iterable[D], f: Callable[[D, D], D]) -> D | Never:
105
117
  def fold_left[D, L](
106
118
  iterable: Iterable[D], f: Callable[[L, D], L], initial: L
107
119
  ) -> L | Never:
108
- """Fold an iterable left with a function and initial value.
109
-
110
- - not restricted to ``__add__`` for the folding function
111
- - initial value required, does not default to ``0`` for initial value
112
- - handles non-numeric data just find
120
+ """
121
+ .. admonition:: fold left
113
122
 
114
- .. Warning::
123
+ Fold an iterable left with a function and initial item.
115
124
 
116
- This function never return if given an infinite iterable.
125
+ - not restricted to ``__add__`` for the folding function
126
+ - initial item is required, does not default to ``0``
127
+ - handles non-numeric data just find
117
128
 
118
- .. Warning::
129
+ :param iterable: iterable to be folded
130
+ :param f: two parameter function, first parameter for accumulated item
131
+ :param initial: mandatory initial item to start fold
132
+ :return: the folded item
119
133
 
120
- This function does not catch any exceptions ``f`` may raise.
134
+ .. warning::
121
135
 
122
- :param iterable: iterable to be folded
123
- :param f: two parameter function, first parameter for accumulated value
124
- :param initial: mandatory initial value to start fold
125
- :return: the folded value
136
+ - never returns if given an infinite iterable
137
+ - does not catch or re-raises exceptions raised by ``f``
126
138
 
127
139
  """
128
140
  acc = initial
@@ -134,24 +146,24 @@ def fold_left[D, L](
134
146
  def maybe_fold_left[D, L](
135
147
  iterable: Iterable[D], f: Callable[[L, D], L], initial: L | NoValue = NoValue()
136
148
  ) -> MayBe[L] | Never:
137
- """Folds an iterable left with an "optional" initial value..
138
-
139
- - when an initial value is not given then ``L = D``
140
- - if iterable empty and no ``initial`` value given, return ``MayBe()``
149
+ """
150
+ .. admonition:: maybe fold left
141
151
 
142
- .. Warning::
152
+ Folds an iterable left with an "optional" initial item.
143
153
 
144
- This function never return if given an infinite iterable.
154
+ - when an initial item is not given then ``L = D``
155
+ - if iterable empty and no ``initial`` item given, return ``MayBe()``
145
156
 
146
- .. Warning::
157
+ :param iterable: The iterable to be folded.
158
+ :param f: First argument is for the accumulated items.
159
+ :param initial: Mandatory initial item to start fold.
160
+ :return: ``MayBe`` of a successfully folded item,
161
+ otherwise returns ``MayBe()``.
147
162
 
148
- This function returns a ``MayBe()`` when ``f`` raises any
149
- exception what-so-ever. The exception is thrown away.
163
+ .. warning::
150
164
 
151
- :param iterable: The iterable to be folded.
152
- :param f: First argument is for the accumulated value.
153
- :param initial: Mandatory initial value to start fold.
154
- :return: MayBe of a successfully folded value, otherwise MayBe()
165
+ - never returns if given an infinite iterable
166
+ - any exception ``f`` raises is thrown away
155
167
 
156
168
  """
157
169
  acc: L
@@ -181,23 +193,33 @@ def sc_reduce_left[D](
181
193
  include_start: bool = True,
182
194
  include_stop: bool = True,
183
195
  ) -> tuple[MayBe[D], Iterator[D]]:
184
- """Short circuit version of a left reduce.
196
+ """
197
+ .. admonition:: short circuit reduce left
198
+
199
+ Short circuit version of a left fold.
200
+
201
+ :param iterable: Iterable to be reduced from the left.
202
+ :param f: Two parameter function, first parameter for
203
+ the accumulator.
204
+ :param start: Delay starting the fold until it returns true.
205
+ :param stop: Prematurely stop the fold when it returns true.
206
+ :param include_start: If true, include starting item in fold.
207
+ :param include_stop: If true, include stopping item in fold.
208
+ :return: Tuple of a ``MayBe`` of the folded item and iterator
209
+ of remaining iterables.
210
+
211
+ .. note::
185
212
 
186
- Useful for infinite iterables.
213
+ Behavior for default arguments will
187
214
 
188
- Behavior for default arguments will
215
+ - left reduce finite iterable
216
+ - start folding immediately
217
+ - continue folding until end (of a possibly infinite iterable)
189
218
 
190
- - left reduce finite iterable
191
- - start folding immediately
192
- - continue folding until end (of a possibly infinite iterable)
219
+ .. tip::
193
220
 
194
- :param iterable: iterable to be reduced from the left
195
- :param f: two parameter function, first parameter for accumulated value
196
- :param start: delay starting the fold until it returns true
197
- :param stop: prematurely stop the fold when it returns true
198
- :param include_start: if true, include fold starting value in fold
199
- :param include_stop: if true, include stopping value in fold
200
- :return: tuple of a MayBe of the folded value and iterator of remaining iterables
221
+ Useful for infinite iterables when Callable ``stop``
222
+ is provided.
201
223
 
202
224
  """
203
225
  it_start = drop_while(iterable, negate(start))
@@ -233,23 +255,32 @@ def sc_reduce_right[D](
233
255
  include_start: bool = True,
234
256
  include_stop: bool = True,
235
257
  ) -> tuple[MayBe[D], Iterator[D]]:
236
- """Short circuit version of a right reduce.
258
+ """
259
+ .. admonition:: short circuit reduce right
260
+
261
+ Short circuit version of a right fold.
262
+
263
+ :param iterable: Iterable to be reduced from the right.
264
+ :param f: Two parameter function, second parameter for
265
+ the accumulator.
266
+ :param start: Delay starting the fold until it returns true.
267
+ :param stop: Prematurely stop the fold when it returns true.
268
+ :param include_start: If true, include starting item.
269
+ :param include_stop: If true, include stopping item in fold.
270
+ :return: Tuple of a ``MayBe`` of the folded item and iterator
271
+ of remaining iterables.
272
+
273
+ .. note::
237
274
 
238
- Useful for infinite and non-reversible iterables.
275
+ Behavior for default arguments will
239
276
 
240
- Behavior for default arguments will
277
+ - right reduce finite iterable
278
+ - start folding at end (of a possibly infinite iterable)
279
+ - continue reducing right until beginning
241
280
 
242
- - right reduce finite iterable
243
- - start folding at end (of a possibly infinite iterable)
244
- - continue reducing right until beginning
281
+ .. tip::
245
282
 
246
- :param iterable: iterable to be reduced from the right
247
- :param f: two parameter function, second parameter for accumulated value
248
- :param start: delay starting the fold until it returns true
249
- :param stop: prematurely stop the fold when it returns true
250
- :param include_start: if true, include fold starting value in fold
251
- :param include_stop: if true, include stopping value in fold
252
- :return: tuple of a MayBe of the folded value and iterator of remaining iterables
283
+ Useful for infinite and non-reversible iterables.
253
284
 
254
285
  """
255
286
  it_start, it_rest = take_while_split(iterable, negate(start))
@@ -1,4 +1,4 @@
1
- # Copyright 2023-2025 Geoffrey R. Scheller
1
+ # Copyright 2023-2026 Geoffrey R. Scheller
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -12,7 +12,12 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- """Module pythonic_fp.iterables.merging"""
15
+ """
16
+ .. admonition:: Merging iterables
17
+
18
+ Functions to merge multiple iterables together into one.
19
+
20
+ """
16
21
 
17
22
  from collections.abc import Iterable, Iterator
18
23
  from enum import auto, Enum
@@ -27,98 +32,112 @@ __all__ = [
27
32
 
28
33
 
29
34
  class MergeEnum(Enum):
30
- """Iterable Blending Enums.
35
+ """
36
+ .. admonition:: Iterable Blending Enums.
31
37
 
32
- - **MergeEnum.Concat:** Concatenate first to last
33
- - **MergeEnum.Merge:** Merge until one is exhausted
34
- - **MergeEnum.Exhaust:** Merge until all are exhausted
38
+ - **MergeEnum.Concat:** Concatenate first to last
39
+ - **MergeEnum.Merge:** Merge until one is exhausted
40
+ - **MergeEnum.Exhaust:** Merge until all are exhausted
35
41
 
36
42
  """
37
-
38
43
  Concat = auto()
39
44
  Merge = auto()
40
45
  Exhaust = auto()
41
46
 
42
47
 
43
48
  def concat[D](*iterables: Iterable[D]) -> Iterator[D]:
44
- """Sequentially concatenate multiple iterables together.
49
+ """
50
+ .. admonition:: concatenate iterables
51
+
52
+ Sequentially concatenate multiple iterables.
45
53
 
46
- .. warning::
47
- An infinite iterable will prevent subsequent iterables from
48
- yielding any values.
54
+ :param iterables: Iterables to concatenate.
55
+ :yields: The concatenated items from all the iterables.
49
56
 
50
- .. note::
57
+ .. warning::
58
+ An infinite iterable will prevent subsequent iterables from
59
+ yielding any items.
51
60
 
52
- Performant to the standard library's ``itertools.chain``.
61
+ .. note::
53
62
 
54
- :param iterables: Iterables to concatenate.
55
- :returns: Iterator of concatenated values from the iterables.
63
+ Performant to the standard library's ``itertools.chain``.
56
64
 
57
65
  """
58
66
  for iterator in map(lambda x: iter(x), iterables):
59
67
  while True:
60
68
  try:
61
- value = next(iterator)
62
- yield value
69
+ item = next(iterator)
70
+ yield item
63
71
  except StopIteration:
64
72
  break
65
73
 
66
74
 
67
75
  def merge[D](*iterables: Iterable[D], yield_partials: bool = False) -> Iterator[D]:
68
- """Merge together ``iterables`` until one is exhausted.
76
+ """
77
+ .. admonition:: merge iterables
69
78
 
70
- .. note::
79
+ Merge multiple iterables until one is exhausted.
71
80
 
72
- When ``yield_partials`` is true, then any unmatched values from other iterables
73
- already yielded when the first iterable is exhausted are yielded. This prevents
74
- data lose if any of the iterables are iterators with external references.
81
+ :param iterables: Iterables to merge until one gets exhausted.
82
+ :param yield_partials: Yield any unpaired yielded items from other iterables.
83
+ :yields: Merged items from the iterables until one of the
84
+ iterables is exhausted.
75
85
 
76
- :param iterables: Iterables to merge until one gets exhausted.
77
- :param yield_partials: Yield any unpaired yielded values from other iterables.
78
- :returns: Iterator of merged values from the iterables until one is exhausted.
86
+ .. note::
87
+
88
+ When ``yield_partials`` is true, then any unmatched items
89
+ from other iterables already yielded when the first iterable
90
+ is exhausted are yielded.
91
+
92
+ This prevents data lose if any of the iterables are
93
+ iterators with external references.
79
94
 
80
95
  """
81
96
  iter_list = list(map(lambda x: iter(x), iterables))
82
- values = []
97
+ items = []
83
98
  if (num_iters := len(iter_list)) > 0:
84
99
  while True:
85
100
  try:
86
101
  for ii in range(num_iters):
87
- values.append(next(iter_list[ii]))
88
- yield from values
89
- values.clear()
102
+ items.append(next(iter_list[ii]))
103
+ yield from items
104
+ items.clear()
90
105
  except StopIteration:
91
106
  break
92
107
  if yield_partials:
93
- yield from values
108
+ yield from items
94
109
 
95
110
 
96
111
  def exhaust[D](*iterables: Iterable[D]) -> Iterator[D]:
97
- """Merge together multiple iterables until all are exhausted.
112
+ """
113
+ .. admonition:: exhaustively merge iterables
98
114
 
99
- :param iterables: Iterables to exhaustively merge.
100
- :returns: Iterator of merged values from the iterables until all are exhausted.
115
+ Merge multiple iterables until all are exhausted.
116
+
117
+ :param iterables: Iterables to exhaustively merge.
118
+ :yields: Merged items from the iterables until all of the
119
+ iterables are exhausted.
101
120
 
102
121
  """
103
122
  iter_list = list(map(lambda x: iter(x), iterables))
104
123
  if (num_iters := len(iter_list)) > 0:
105
124
  ii = 0
106
- values = []
125
+ items = []
107
126
  while True:
108
127
  try:
109
128
  while ii < num_iters:
110
- values.append(next(iter_list[ii]))
129
+ items.append(next(iter_list[ii]))
111
130
  ii += 1
112
- yield from values
131
+ yield from items
113
132
  ii = 0
114
- values.clear()
133
+ items.clear()
115
134
  except StopIteration:
116
135
  num_iters -= 1
117
136
  if num_iters < 1:
118
137
  break
119
138
  del iter_list[ii]
120
139
 
121
- yield from values
140
+ yield from items
122
141
 
123
142
 
124
143
  def blend[D](
@@ -126,13 +145,16 @@ def blend[D](
126
145
  merge_enum: MergeEnum = MergeEnum.Concat,
127
146
  yield_partials: bool = False,
128
147
  ) -> Iterator[D]:
129
- """Base merge behavior on name only parameters.
148
+ """
149
+ .. admonition:: merge iterables
150
+
151
+ Merge behavior based on value of merge_enum parameter.
130
152
 
131
- :param iterables: Iterables to blend together.
132
- :param merge_enum: ``MergeEnum`` to determine merging behavior.
133
- :param yield_partials: Yield unpaired values from other iterables.
134
- :returns: An iterator of type ``D``.
135
- :raises ValueError: When an unknown ``MergeEnum`` is given.
153
+ :param iterables: Iterables to blend together.
154
+ :param merge_enum: ``MergeEnum`` to determine merging behavior.
155
+ :param yield_partials: Yield unpaired items from other iterables.
156
+ :yields: Items from all iterables blended together.
157
+ :raises ValueError: When an unknown ``MergeEnum`` is given.
136
158
 
137
159
  """
138
160
  match merge_enum:
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pythonic-fp-iterables
3
- Version: 5.1.2
4
- Summary: Library of functions for iterating iterables
3
+ Version: 5.1.4
4
+ Summary: .. admonition:: Composing and iterating iterables
5
5
  Keywords: iterables,iterators
6
6
  Author-email: "Geoffrey R. Scheller" <geoffrey@scheller.com>
7
7
  Requires-Python: >=3.13
@@ -11,15 +11,15 @@ Classifier: Framework :: Pytest
11
11
  Classifier: Intended Audience :: Developers
12
12
  Classifier: License :: OSI Approved :: Apache Software License
13
13
  Classifier: Operating System :: OS Independent
14
- Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Programming Language :: Python :: 3.14
15
15
  Classifier: Typing :: Typed
16
16
  License-File: LICENSE
17
- Requires-Dist: pythonic-fp-fptools>=5.1.2
18
- Requires-Dist: pythonic-fp-gadgets>=3.1.0
17
+ Requires-Dist: pythonic-fp-fptools>=5.2.0
18
+ Requires-Dist: pythonic-fp-gadgets>=4.0.2
19
19
  Requires-Dist: pytest>=8.4.1 ; extra == "test"
20
20
  Project-URL: Changelog, https://github.com/grscheller/pythonic-fp-iterables/blob/main/CHANGELOG.rst
21
- Project-URL: Documentation, https://grscheller.github.io/pythonic-fp/iterables/development/build/html/
22
- Project-URL: Homepage, https://grscheller.github.io/pythonic-fp/homepage/build/html/
21
+ Project-URL: Documentation, https://grscheller.github.io/pythonic-fp/projects/iterables.html
22
+ Project-URL: Homepage, https://grscheller.github.io/pythonic-fp/
23
23
  Project-URL: Source, https://github.com/grscheller/pythonic-fp-iterables
24
24
  Provides-Extra: test
25
25
 
@@ -27,7 +27,8 @@ Pythonic FP - Tools for iterables
27
27
  =================================
28
28
 
29
29
  PyPI project
30
- `pythonic-fp.iterators <https://pypi.org/project/pythonic-fp.iterables>`_.
30
+ `pythonic-fp-iterators
31
+ <https://pypi.org/project/pythonic-fp-iterables>`_.
31
32
 
32
33
  Library of functions for iterating iterables.
33
34
 
@@ -44,19 +45,19 @@ Library of functions for iterating iterables.
44
45
 
45
46
  Part of the
46
47
  `pythonic-fp
47
- <https://grscheller.github.io/pythonic-fp/homepage/build/html/index.html>`_
48
+ <https://grscheller.github.io/pythonic-fp/>`_
48
49
  PyPI projects.
49
50
 
50
51
  Documentation
51
52
  -------------
52
53
 
53
- Documentation for this project is hosted on
54
+ Documentation and other links for this project are hosted on
54
55
  `GitHub Pages
55
- <https://grscheller.github.io/pythonic-fp/iterables/development/build/html>`_.
56
+ <https://grscheller.github.io/pythonic-fp/projects/iterables.html>`_.
56
57
 
57
58
  Copyright and License
58
59
  ---------------------
59
60
 
60
- Copyright (c) 2023-2025 Geoffrey R. Scheller. Licensed under the Apache
61
+ Copyright (c) 2023-2026 Geoffrey R. Scheller. Licensed under the Apache
61
62
  License, Version 2.0. See the LICENSE file for details.
62
63
 
@@ -0,0 +1,13 @@
1
+ pythonic_fp/iterables/__init__.py,sha256=j-Z9XV73LehhLwYvi_Wzhml7hPaEbHiRjRJt-BI6RKs,1255
2
+ pythonic_fp/iterables/__init__.pyi,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ pythonic_fp/iterables/drop_take.py,sha256=0ydMGx-aj_-aK5PIx7Rowh_9h0niC6bRKMSotHjvy1g,5558
4
+ pythonic_fp/iterables/drop_take.pyi,sha256=vPyByY4PxCGEuL6trI0aTK8fBr4xCuOgqhaKALwJ5Ys,653
5
+ pythonic_fp/iterables/folding.py,sha256=tqFzxzWLpK6qIS9ff8tTwv58q2h4gjBAyuHrNeEWi20,9347
6
+ pythonic_fp/iterables/folding.pyi,sha256=ZVrpB-D4kWoVwpCsQ2rc3GJ8iTzavAOQ5YK9LteAukU,1175
7
+ pythonic_fp/iterables/merging.py,sha256=acQ8_Iw07CVvOnB_D8dbLvmkjv7P48CysareWlfAbRc,4912
8
+ pythonic_fp/iterables/merging.pyi,sha256=KnuSFREXEpnbtTvMWsvn-KfeSjZ3ybP-6n9hCxjNKVs,533
9
+ pythonic_fp/iterables/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ pythonic_fp_iterables-5.1.4.dist-info/licenses/LICENSE,sha256=IJMkVWQUVy-SonK6SMaMotDQ6Zb-lVi2bUTiGp1GUO8,10774
11
+ pythonic_fp_iterables-5.1.4.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
12
+ pythonic_fp_iterables-5.1.4.dist-info/METADATA,sha256=zOdoxJujuqsKpXHZqKfI-0wJRmnKEDdy5T_KjMXMJGQ,2096
13
+ pythonic_fp_iterables-5.1.4.dist-info/RECORD,,
@@ -1,13 +0,0 @@
1
- pythonic_fp/iterables/__init__.py,sha256=UTde8stsDVG_5Z7fo37yiYeTu8fhkkv0QsQcQb_ixTU,1590
2
- pythonic_fp/iterables/__init__.pyi,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- pythonic_fp/iterables/drop_take.py,sha256=VpcnQp0Nr4bUGXb-TD2UFl5kHo1fllAFoV_hlYHo8G0,4772
4
- pythonic_fp/iterables/drop_take.pyi,sha256=vPyByY4PxCGEuL6trI0aTK8fBr4xCuOgqhaKALwJ5Ys,653
5
- pythonic_fp/iterables/folding.py,sha256=lUvQzRU1wFbolw-b3bI1oU_xk7yIj2V5J8WA-qQxvUc,8612
6
- pythonic_fp/iterables/folding.pyi,sha256=ZVrpB-D4kWoVwpCsQ2rc3GJ8iTzavAOQ5YK9LteAukU,1175
7
- pythonic_fp/iterables/merging.py,sha256=CiBYp-iAr-iQrVTWK0wOkFDs9EJ9139p_MRiffIZJ2s,4485
8
- pythonic_fp/iterables/merging.pyi,sha256=KnuSFREXEpnbtTvMWsvn-KfeSjZ3ybP-6n9hCxjNKVs,533
9
- pythonic_fp/iterables/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- pythonic_fp_iterables-5.1.2.dist-info/licenses/LICENSE,sha256=IJMkVWQUVy-SonK6SMaMotDQ6Zb-lVi2bUTiGp1GUO8,10774
11
- pythonic_fp_iterables-5.1.2.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
12
- pythonic_fp_iterables-5.1.2.dist-info/METADATA,sha256=G2d_xgzY-1WoYRBu-QoJbAO9PbV5O3uzcchy9fOO6ho,2143
13
- pythonic_fp_iterables-5.1.2.dist-info/RECORD,,