python-iterutils 0.2.5.5__tar.gz → 0.2.7__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-iterutils
3
- Version: 0.2.5.5
3
+ Version: 0.2.7
4
4
  Summary: Python another itertools.
5
5
  Home-page: https://github.com/ChenyangGao/web-mount-packs/tree/main/python-module/python-iterutils
6
6
  License: MIT
@@ -2,14 +2,13 @@
2
2
  # encoding: utf-8
3
3
 
4
4
  __author__ = "ChenyangGao <https://chenyanggao.github.io>"
5
- __version__ = (0, 2, 5)
5
+ __version__ = (0, 2, 7)
6
6
  __all__ = [
7
- "Yield", "YieldFrom", "iterable", "async_iterable",
8
- "run_gen_step", "run_gen_step_iter", "as_gen_step",
9
- "as_gen_step_iter", "split_cm", "with_iter_next",
10
- "map", "filter", "reduce", "zip", "chain",
11
- "chain_from_iterable", "chunked", "foreach",
12
- "async_foreach", "through", "async_through",
7
+ "Yield", "YieldFrom", "GenStep", "GenStepIter", "iterable",
8
+ "async_iterable", "run_gen_step", "run_gen_step_iter",
9
+ "as_gen_step", "as_gen_step_iter", "split_cm", "with_iter_next",
10
+ "map", "filter", "reduce", "zip", "chain", "chain_from_iterable",
11
+ "chunked", "foreach", "async_foreach", "through", "async_through",
13
12
  "flatten", "async_flatten", "collect", "async_collect",
14
13
  "group_collect", "async_group_collect", "iter_unique",
15
14
  "async_iter_unique", "wrap_iter", "wrap_aiter", "acc_step",
@@ -63,6 +62,22 @@ class YieldFrom:
63
62
  value: Any
64
63
 
65
64
 
65
+ @dataclass(slots=True, frozen=True, unsafe_hash=True)
66
+ class GenStep:
67
+ """专供 `run_gen_step` 和 `run_gen_step_iter`,说明值需要进一步提取
68
+ """
69
+ value: Generator
70
+ max_depth: int = 0
71
+
72
+
73
+ @dataclass(slots=True, frozen=True, unsafe_hash=True)
74
+ class GenStepIter:
75
+ """专供 `run_gen_step_iter`,说明值需要进一步提取
76
+ """
77
+ value: Generator
78
+ max_depth: int = 0
79
+
80
+
66
81
  iterable = Iterable.__instancecheck__
67
82
  async_iterable = AsyncIterable.__instancecheck__
68
83
  isawaitable = Awaitable.__instancecheck__
@@ -91,37 +106,68 @@ def _get_async[T](back: int = 2, /, *, default: Literal[False] | T = False) -> b
91
106
  return _coalesce(iter_frams(), default)
92
107
 
93
108
 
94
- def _run_gen_step(gen: Generator, /):
95
- send = gen.send
109
+ def _run_gen_step(
110
+ gen: Generator,
111
+ /,
112
+ drive_generator: int = 0,
113
+ ):
114
+ send = gen.send
115
+ throw = gen.throw
116
+ dgen = drive_generator if drive_generator < 0 else drive_generator - 1
96
117
  try:
97
118
  value: Any = send(None)
98
119
  while True:
99
- value = send(value)
120
+ try:
121
+ if isinstance(value, GenStep):
122
+ value = _run_gen_step(value.value, value.max_depth)
123
+ elif drive_generator and isinstance(value, Generator):
124
+ value = _run_gen_step(value, dgen)
125
+ except BaseException as e:
126
+ value = throw(e)
127
+ else:
128
+ value = send(value)
100
129
  except StopIteration as e:
101
- return e.value
130
+ value = e.value
131
+ if isinstance(value, GenStep):
132
+ value = _run_gen_step(value.value, value.max_depth)
133
+ elif drive_generator and isinstance(value, Generator):
134
+ value = _run_gen_step(value, dgen)
135
+ return value
102
136
  finally:
103
137
  gen.close()
104
138
 
105
139
 
106
- async def _run_gen_step_async(gen: Generator, /):
140
+ async def _run_gen_step_async(
141
+ gen: Generator,
142
+ /,
143
+ drive_generator: int = 0,
144
+ ):
107
145
  send = gen.send
108
146
  throw = gen.throw
147
+ dgen = drive_generator if drive_generator < 0 else drive_generator - 1
109
148
  try:
110
- ret: Any = send(None)
149
+ value: Any = send(None)
111
150
  while True:
112
- if isawaitable(ret):
113
- try:
114
- value: Any = (await ret)
115
- except BaseException as e:
116
- ret = throw(e)
117
- else:
118
- ret = send(value)
151
+ try:
152
+ if isawaitable(value):
153
+ value = await value
154
+ elif isinstance(value, GenStep):
155
+ value = await _run_gen_step_async(value.value, value.max_depth)
156
+ elif drive_generator and isinstance(value, Generator):
157
+ value = await _run_gen_step_async(value, dgen)
158
+ except BaseException as e:
159
+ value = throw(e)
119
160
  else:
120
- ret = send(ret)
161
+ value = send(value)
121
162
  except StopIteration as e:
122
- if isawaitable(e.value):
123
- return await e.value
124
- return e.value
163
+ value = e.value
164
+ if isawaitable(value):
165
+ value = await value
166
+ elif isinstance(value, GenStep):
167
+ value = await _run_gen_step_async(value.value, value.max_depth)
168
+ elif drive_generator and isinstance(value, Generator):
169
+ value = await _run_gen_step_async(value, dgen)
170
+ return value
125
171
  finally:
126
172
  gen.close()
127
173
 
@@ -150,69 +196,114 @@ def run_gen_step[**Args](
150
196
  return _run_gen_step(gen_step)
151
197
 
152
198
 
153
- def _run_gen_step_iter(gen: Generator, /) -> Iterator:
154
- send = gen.send
199
+ def _run_gen_step_iter(
200
+ gen: Generator,
201
+ /,
202
+ drive_generator: int = 0,
203
+ ) -> Iterator:
204
+ send = gen.send
205
+ throw = gen.throw
206
+ dgen = drive_generator if drive_generator < 0 else drive_generator - 1
155
207
  try:
156
208
  value: Any = send(None)
157
209
  while True:
158
- if isinstance(value, Yield):
159
- yield value.value
160
- elif isinstance(value, YieldFrom):
161
- yield from value.value
162
- value = send(value)
210
+ try:
211
+ val_type = type(value)
212
+ if issubclass(val_type, (Yield, YieldFrom)):
213
+ value = value.value
214
+ elif isinstance(value, GenStepIter):
215
+ yield from _run_gen_step_iter(value.value, value.max_depth)
216
+ elif isinstance(value, GenStep):
217
+ value = _run_gen_step(value.value, value.max_depth)
218
+ elif drive_generator and isinstance(value, Generator):
219
+ value = _run_gen_step(value, dgen)
220
+ if val_type is Yield:
221
+ yield value
222
+ elif val_type is YieldFrom:
223
+ yield from value
224
+ except BaseException as e:
225
+ value = throw(e)
226
+ else:
227
+ value = send(value)
163
228
  except StopIteration as e:
164
229
  value = e.value
165
- if isinstance(value, Yield):
166
- yield value.value
167
- elif isinstance(value, YieldFrom):
168
- yield from value.value
230
+ val_type = type(value)
231
+ if issubclass(val_type, (Yield, YieldFrom)):
232
+ value = value.value
233
+ elif isinstance(value, GenStepIter):
234
+ yield from _run_gen_step_iter(value.value, value.max_depth)
235
+ elif isinstance(value, GenStep):
236
+ value = _run_gen_step(value.value, value.max_depth)
237
+ elif drive_generator and isinstance(value, Generator):
238
+ value = _run_gen_step(value, dgen)
239
+ if val_type is Yield:
240
+ yield value
241
+ elif val_type is YieldFrom:
242
+ yield from value
169
243
  finally:
170
244
  gen.close()
171
245
 
172
246
 
173
- async def _run_gen_step_async_iter(gen: Generator, /) -> AsyncIterator:
247
+ async def _run_gen_step_async_iter(
248
+ gen: Generator,
249
+ /,
250
+ drive_generator: int = 0,
251
+ ) -> AsyncIterator:
174
252
  send = gen.send
175
253
  throw = gen.throw
254
+ dgen = drive_generator if drive_generator < 0 else drive_generator - 1
176
255
  try:
177
- ret: Any = send(None)
256
+ value: Any = send(None)
178
257
  while True:
179
258
  try:
180
- if isinstance(ret, (Yield, YieldFrom)):
181
- value: Any = ret.value
182
- if isawaitable(value):
183
- value = await value
184
- if isinstance(ret, Yield):
185
- yield value
186
- elif isinstance(value, AsyncIterable):
187
- async for e in value:
188
- yield e
259
+ val_type = type(value)
260
+ if issubclass(val_type, (Yield, YieldFrom)):
261
+ value = value.value
262
+ if isawaitable(value):
263
+ value = await value
264
+ elif isinstance(value, GenStepIter):
265
+ async for el in _run_gen_step_async_iter(value.value, value.max_depth):
266
+ yield el
267
+ elif isinstance(value, GenStep):
268
+ value = await _run_gen_step_async(value.value, value.max_depth)
269
+ elif drive_generator and isinstance(value, Generator):
270
+ value = await _run_gen_step_async(value, dgen)
271
+ if val_type is Yield:
272
+ yield value
273
+ elif val_type is YieldFrom:
274
+ if isinstance(value, AsyncIterable):
275
+ async for el in value:
276
+ yield el
189
277
  else:
190
- for e in value:
191
- yield e
192
- elif isawaitable(ret):
193
- value = await ret
194
- else:
195
- value = ret
278
+ for el in value:
279
+ yield el
196
280
  except BaseException as e:
197
- ret = throw(e)
281
+ value = throw(e)
198
282
  else:
199
- ret = send(value)
283
+ value = send(value)
200
284
  except StopIteration as e:
201
- val = e.value
202
- if isinstance(val, (Yield, YieldFrom)):
203
- value = val.value
204
- if isawaitable(value):
205
- value = await value
206
- if isinstance(ret, Yield):
207
- yield value
208
- elif isinstance(value, AsyncIterable):
209
- async for e in value:
210
- yield e
285
+ value = e.value
286
+ val_type = type(value)
287
+ if issubclass(val_type, (Yield, YieldFrom)):
288
+ value = value.value
289
+ if isawaitable(value):
290
+ value = await value
291
+ elif isinstance(value, GenStepIter):
292
+ async for el in _run_gen_step_async_iter(value.value, value.max_depth):
293
+ yield el
294
+ elif isinstance(value, GenStep):
295
+ value = await _run_gen_step_async(value.value, value.max_depth)
296
+ elif drive_generator and isinstance(value, Generator):
297
+ value = await _run_gen_step_async(value, dgen)
298
+ if val_type is Yield:
299
+ yield value
300
+ elif val_type is YieldFrom:
301
+ if isinstance(value, AsyncIterable):
302
+ async for el in value:
303
+ yield el
211
304
  else:
212
- for e in value:
213
- yield e
214
- elif isawaitable(val):
215
- await val
305
+ for el in value:
306
+ yield el
216
307
  finally:
217
308
  gen.close()
218
309
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "python-iterutils"
3
- version = "0.2.5.5"
3
+ version = "0.2.7"
4
4
  description = "Python another itertools."
5
5
  authors = ["ChenyangGao <wosiwujm@gmail.com>"]
6
6
  license = "MIT"