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