python-iterutils 0.2.5.1__tar.gz → 0.2.5.3__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.1
3
+ Version: 0.2.5.3
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
@@ -6,7 +6,7 @@ __version__ = (0, 2, 5)
6
6
  __all__ = [
7
7
  "Yield", "YieldFrom", "iterable", "async_iterable",
8
8
  "run_gen_step", "run_gen_step_iter", "as_gen_step",
9
- "as_gen_step_iter", "split_cm, ""with_iter_next",
9
+ "as_gen_step_iter", "split_cm", "with_iter_next",
10
10
  "map", "filter", "reduce", "zip", "chain",
11
11
  "chain_from_iterable", "chunked", "foreach",
12
12
  "async_foreach", "through", "async_through",
@@ -32,7 +32,7 @@ from contextlib import (
32
32
  from copy import copy
33
33
  from dataclasses import dataclass
34
34
  from itertools import batched, chain as _chain, pairwise
35
- from inspect import isawaitable, iscoroutinefunction, signature
35
+ from inspect import iscoroutinefunction, signature
36
36
  from sys import _getframe, exc_info
37
37
  from _thread import start_new_thread
38
38
  from time import sleep, time
@@ -63,36 +63,32 @@ class YieldFrom:
63
63
  value: Any
64
64
 
65
65
 
66
- def iterable(obj, /) -> bool:
67
- """判断对象是不是 Iterable
68
- """
69
- return isinstance(obj, Iterable)
66
+ iterable = Iterable.__instancecheck__
67
+ async_iterable = AsyncIterable.__instancecheck__
68
+ isawaitable = Awaitable.__instancecheck__
70
69
 
71
70
 
72
- def async_iterable(obj, /) -> bool:
73
- """判断对象是不是 AsyncIterable
74
- """
75
- return isinstance(obj, AsyncIterable)
71
+ def _coalesce(vals, default=None):
72
+ for val in vals:
73
+ if val is not None:
74
+ return val
75
+ return default
76
76
 
77
77
 
78
- def _get_async(back: int = 2, /) -> bool:
78
+ @overload
79
+ def _get_async(back: int = 2, /, *, default: Literal[False] = False) -> bool:
80
+ ...
81
+ @overload
82
+ def _get_async[T](back: int = 2, /, *, default: T) -> bool | T:
83
+ ...
84
+ def _get_async[T](back: int = 2, /, *, default: Literal[False] | T = False) -> bool | T:
79
85
  """往上查找,从最近的调用栈的命名空间中获取 `async_` 的值
80
86
  """
81
- f: None | FrameType
82
- f = _getframe(back)
83
- f_globals = f.f_globals
84
- f_locals = f.f_locals
85
- if f_locals is f_globals:
86
- return f_locals.get("async_") or False
87
- while f_locals is not None and f_locals is not f_globals:
88
- if "async_" in f_locals:
89
- if f_locals["async_"] is not None:
90
- return f_locals["async_"]
91
- f = f.f_back
92
- if f is None:
93
- break
94
- f_locals = f.f_locals
95
- return False
87
+ def iter_frams(f: None | FrameType = _getframe(back)):
88
+ while f:
89
+ yield f.f_locals.get("async_")
90
+ f = f.f_back
91
+ return _coalesce(iter_frams(), default)
96
92
 
97
93
 
98
94
  def _run_gen_step(gen: Generator, /):
@@ -111,14 +107,17 @@ async def _run_gen_step_async(gen: Generator, /):
111
107
  send = gen.send
112
108
  throw = gen.throw
113
109
  try:
114
- ret: Awaitable = send(None)
110
+ ret: Any = send(None)
115
111
  while True:
116
- try:
117
- value: Any = await ret
118
- except BaseException as e:
119
- ret = throw(e)
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)
120
119
  else:
121
- ret = send(value)
120
+ ret = send(ret)
122
121
  except StopIteration as e:
123
122
  if isawaitable(e.value):
124
123
  return await e.value
@@ -175,10 +174,10 @@ async def _run_gen_step_async_iter(gen: Generator, /) -> AsyncIterator:
175
174
  send = gen.send
176
175
  throw = gen.throw
177
176
  try:
178
- ret: Awaitable | Yield | YieldFrom = send(None)
177
+ ret: Any = send(None)
179
178
  while True:
180
179
  try:
181
- if isinstance(ret, Awaitable):
180
+ if isawaitable(ret):
182
181
  value: Any = await ret
183
182
  else:
184
183
  value = ret.value
@@ -271,10 +270,14 @@ def as_gen_step[**Args](
271
270
  gen_step: Callable[Args, Generator],
272
271
  /,
273
272
  ) -> Callable[Args, Any]:
273
+ default_async = _get_async(default=None)
274
274
  def wrapper(*args: Args.args, **kwds: Args.kwargs):
275
275
  return run_gen_step(
276
276
  gen_step,
277
- cast(None | Literal[False, True], kwds.pop("async_", None)),
277
+ _coalesce((
278
+ kwds.pop("async_", None),
279
+ _get_async(default=default_async),
280
+ )),
278
281
  *args,
279
282
  **kwds,
280
283
  )
@@ -285,10 +288,14 @@ def as_gen_step_iter[**Args](
285
288
  gen_step: Callable[Args, Generator],
286
289
  /,
287
290
  ) -> Callable[Args, Iterable | AsyncIterable]:
291
+ default_async = _get_async(default=None)
288
292
  def wrapper(*args: Args.args, **kwds: Args.kwargs):
289
293
  return run_gen_step_iter(
290
294
  gen_step,
291
- cast(None | Literal[False, True], kwds.pop("async_", None)),
295
+ _coalesce((
296
+ kwds.pop("async_", None),
297
+ _get_async(default=default_async),
298
+ )),
292
299
  *args,
293
300
  **kwds,
294
301
  )
@@ -1113,7 +1120,7 @@ def context[T](
1113
1120
  add_arg(enter(ctx))
1114
1121
  ret = func(*args)
1115
1122
  if isawaitable(ret):
1116
- ret = await ret
1123
+ ret = await cast(Awaitable, ret)
1117
1124
  return ret
1118
1125
  return call()
1119
1126
  else:
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "python-iterutils"
3
- version = "0.2.5.1"
3
+ version = "0.2.5.3"
4
4
  description = "Python another itertools."
5
5
  authors = ["ChenyangGao <wosiwujm@gmail.com>"]
6
6
  license = "MIT"