omlish 0.0.0.dev195__py3-none-any.whl → 0.0.0.dev197__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- omlish/__about__.py +3 -3
- omlish/asyncs/asyncio/all.py +0 -1
- omlish/asyncs/asyncio/asyncio.py +2 -6
- omlish/asyncs/bluelet/runner.py +1 -1
- omlish/asyncs/bridge.py +2 -2
- omlish/codecs/base.py +5 -5
- omlish/codecs/text.py +1 -2
- omlish/io/compress/adapters.py +4 -4
- omlish/io/compress/base.py +4 -4
- omlish/io/compress/bz2.py +4 -4
- omlish/io/compress/codecs.py +2 -2
- omlish/io/compress/gzip.py +10 -10
- omlish/io/compress/lz4.py +5 -5
- omlish/io/compress/lzma.py +4 -4
- omlish/io/compress/zlib.py +4 -4
- omlish/io/coro/__init__.py +56 -0
- omlish/io/coro/direct.py +13 -0
- omlish/io/{generators → coro}/readers.py +31 -31
- omlish/io/{generators → coro}/stepped.py +28 -28
- omlish/multiprocessing/__init__.py +32 -0
- omlish/{multiprocessing.py → multiprocessing/death.py} +3 -88
- omlish/multiprocessing/proxies.py +30 -0
- omlish/multiprocessing/spawn.py +59 -0
- omlish/os/atomics.py +2 -2
- omlish/outcome.py +250 -0
- omlish/sockets/server.py +1 -2
- omlish/term/vt100/terminal.py +1 -1
- omlish/testing/pytest/__init__.py +0 -4
- omlish/testing/pytest/plugins/asyncs/__init__.py +1 -0
- omlish/testing/pytest/plugins/asyncs/backends/__init__.py +16 -0
- omlish/testing/pytest/plugins/asyncs/backends/asyncio.py +35 -0
- omlish/testing/pytest/plugins/asyncs/backends/base.py +30 -0
- omlish/testing/pytest/plugins/asyncs/backends/trio.py +91 -0
- omlish/testing/pytest/plugins/asyncs/backends/trio_asyncio.py +89 -0
- omlish/testing/pytest/plugins/asyncs/consts.py +3 -0
- omlish/testing/pytest/plugins/asyncs/fixtures.py +273 -0
- omlish/testing/pytest/plugins/asyncs/plugin.py +182 -0
- omlish/testing/pytest/plugins/asyncs/utils.py +10 -0
- omlish/testing/pytest/plugins/managermarks.py +0 -14
- omlish/text/indent.py +1 -1
- omlish/text/minja.py +2 -2
- {omlish-0.0.0.dev195.dist-info → omlish-0.0.0.dev197.dist-info}/METADATA +5 -5
- {omlish-0.0.0.dev195.dist-info → omlish-0.0.0.dev197.dist-info}/RECORD +48 -36
- {omlish-0.0.0.dev195.dist-info → omlish-0.0.0.dev197.dist-info}/WHEEL +1 -1
- omlish/io/generators/__init__.py +0 -56
- omlish/io/generators/direct.py +0 -13
- omlish/testing/pytest/marks.py +0 -18
- omlish/testing/pytest/plugins/asyncs.py +0 -162
- /omlish/io/{generators → coro}/consts.py +0 -0
- {omlish-0.0.0.dev195.dist-info → omlish-0.0.0.dev197.dist-info}/LICENSE +0 -0
- {omlish-0.0.0.dev195.dist-info → omlish-0.0.0.dev197.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev195.dist-info → omlish-0.0.0.dev197.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,182 @@
|
|
1
|
+
"""
|
2
|
+
TODO:
|
3
|
+
- auto drain_asyncio
|
4
|
+
"""
|
5
|
+
import contextvars
|
6
|
+
import functools
|
7
|
+
import sys
|
8
|
+
import typing as ta
|
9
|
+
import warnings
|
10
|
+
|
11
|
+
import pytest
|
12
|
+
from _pytest.outcomes import Skipped # noqa
|
13
|
+
from _pytest.outcomes import XFailed # noqa
|
14
|
+
|
15
|
+
from ..... import check
|
16
|
+
from ..... import lang
|
17
|
+
from .._registry import register
|
18
|
+
from .backends import ASYNC_BACKENDS
|
19
|
+
from .backends import AsyncsBackend
|
20
|
+
from .consts import ASYNCS_MARK
|
21
|
+
from .consts import PARAM_NAME
|
22
|
+
from .fixtures import CANARY
|
23
|
+
from .fixtures import AsyncsFixture
|
24
|
+
from .fixtures import AsyncsTestContext
|
25
|
+
from .fixtures import is_asyncs_fixture
|
26
|
+
from .utils import is_async_function
|
27
|
+
from .utils import is_coroutine_function
|
28
|
+
|
29
|
+
|
30
|
+
if ta.TYPE_CHECKING:
|
31
|
+
import anyio
|
32
|
+
else:
|
33
|
+
anyio = lang.proxy_import('anyio')
|
34
|
+
|
35
|
+
|
36
|
+
##
|
37
|
+
|
38
|
+
|
39
|
+
@register
|
40
|
+
class AsyncsPlugin:
|
41
|
+
def __init__(self, backends: ta.Collection[type[AsyncsBackend]] | None = None) -> None:
|
42
|
+
super().__init__()
|
43
|
+
|
44
|
+
if backends is None:
|
45
|
+
backends = ASYNC_BACKENDS
|
46
|
+
|
47
|
+
bd: dict[str, AsyncsBackend] = {}
|
48
|
+
for bc in backends:
|
49
|
+
be = bc()
|
50
|
+
if not be.is_available():
|
51
|
+
continue
|
52
|
+
bn = be.name
|
53
|
+
check.not_in(bn, bd)
|
54
|
+
bd[bn] = be
|
55
|
+
self._backends = bd
|
56
|
+
|
57
|
+
def pytest_cmdline_main(self, config):
|
58
|
+
if (aio_plugin := sys.modules.get('pytest_asyncio.plugin')):
|
59
|
+
# warnings.filterwarnings is clobbered by pytest using warnings.catch_warnings
|
60
|
+
def aio_plugin_warn(message, *args, **kwargs):
|
61
|
+
if (
|
62
|
+
isinstance(message, pytest.PytestDeprecationWarning) and
|
63
|
+
message.args[0].startswith('The configuration option "asyncio_default_fixture_loop_scope" is unset.') # noqa
|
64
|
+
):
|
65
|
+
return
|
66
|
+
warnings.warn(message, *args, **kwargs)
|
67
|
+
|
68
|
+
aio_plugin.warnings = lang.proxy_import('warnings') # type: ignore
|
69
|
+
aio_plugin.warnings.warn = aio_plugin_warn # type: ignore
|
70
|
+
|
71
|
+
def pytest_configure(self, config):
|
72
|
+
config.addinivalue_line('markers', f'{ASYNCS_MARK}: marks for all async backends')
|
73
|
+
|
74
|
+
def pytest_generate_tests(self, metafunc):
|
75
|
+
if (m := metafunc.definition.get_closest_marker(ASYNCS_MARK)) is not None:
|
76
|
+
if m.args:
|
77
|
+
bns = m.args
|
78
|
+
else:
|
79
|
+
bns = list(self._backends)
|
80
|
+
else:
|
81
|
+
return
|
82
|
+
|
83
|
+
for bn in bns:
|
84
|
+
be = self._backends[bn]
|
85
|
+
be.prepare_for_metafunc(metafunc)
|
86
|
+
|
87
|
+
metafunc.fixturenames.append(PARAM_NAME)
|
88
|
+
metafunc.parametrize(PARAM_NAME, bns)
|
89
|
+
|
90
|
+
def pytest_fixture_setup(self, fixturedef, request):
|
91
|
+
is_asyncs_test = request.node.get_closest_marker(ASYNCS_MARK) is not None
|
92
|
+
|
93
|
+
kwargs = {name: request.getfixturevalue(name) for name in fixturedef.argnames}
|
94
|
+
|
95
|
+
if not is_asyncs_fixture(fixturedef.func, is_asyncs_test, kwargs):
|
96
|
+
return None
|
97
|
+
|
98
|
+
if request.scope != 'function':
|
99
|
+
raise RuntimeError('Asyncs fixtures must be function-scope')
|
100
|
+
|
101
|
+
if not is_asyncs_test:
|
102
|
+
raise RuntimeError('Asyncs fixtures can only be used by Asyncs tests')
|
103
|
+
|
104
|
+
fixture = AsyncsFixture(
|
105
|
+
'<fixture {!r}>'.format(fixturedef.argname), # noqa
|
106
|
+
fixturedef.func,
|
107
|
+
kwargs,
|
108
|
+
)
|
109
|
+
|
110
|
+
fixturedef.cached_result = (fixture, request.param_index, None)
|
111
|
+
|
112
|
+
return fixture
|
113
|
+
|
114
|
+
@pytest.hookimpl(hookwrapper=True)
|
115
|
+
def pytest_runtest_call(self, item):
|
116
|
+
if (m := item.get_closest_marker(ASYNCS_MARK)) is None: # noqa
|
117
|
+
if is_async_function(item.obj):
|
118
|
+
from _pytest.unittest import UnitTestCase # noqa
|
119
|
+
if isinstance(item.parent, UnitTestCase):
|
120
|
+
# unittest handles these itself.
|
121
|
+
pass
|
122
|
+
else:
|
123
|
+
raise Exception(f'{item.nodeid}: async def function and no async plugin specified')
|
124
|
+
|
125
|
+
yield
|
126
|
+
return
|
127
|
+
|
128
|
+
bn = item.callspec.params[PARAM_NAME]
|
129
|
+
be = self._backends[bn]
|
130
|
+
|
131
|
+
item.obj = self.test_runner_factory(be, item)
|
132
|
+
|
133
|
+
yield
|
134
|
+
|
135
|
+
def test_runner_factory(self, backend: AsyncsBackend, item, testfunc=None):
|
136
|
+
if not testfunc:
|
137
|
+
testfunc = item.obj
|
138
|
+
|
139
|
+
if not is_coroutine_function(testfunc):
|
140
|
+
pytest.fail(f'test function `{item!r}` is marked asyncs but is not async')
|
141
|
+
|
142
|
+
@backend.wrap_runner
|
143
|
+
async def _bootstrap_fixtures_and_run_test(**kwargs):
|
144
|
+
__tracebackhide__ = True
|
145
|
+
|
146
|
+
test_ctx = AsyncsTestContext(backend)
|
147
|
+
test = AsyncsFixture(
|
148
|
+
'<test {!r}>'.format(testfunc.__name__), # noqa
|
149
|
+
testfunc,
|
150
|
+
kwargs,
|
151
|
+
is_test=True,
|
152
|
+
)
|
153
|
+
|
154
|
+
contextvars_ctx = contextvars.copy_context()
|
155
|
+
contextvars_ctx.run(CANARY.set, 'in correct context')
|
156
|
+
|
157
|
+
async with anyio.create_task_group() as nursery:
|
158
|
+
for fixture in test.register_and_collect_dependencies():
|
159
|
+
contextvars_ctx.run(
|
160
|
+
functools.partial(
|
161
|
+
nursery.start_soon,
|
162
|
+
fixture.run,
|
163
|
+
test_ctx,
|
164
|
+
contextvars_ctx,
|
165
|
+
name=fixture.name,
|
166
|
+
),
|
167
|
+
)
|
168
|
+
|
169
|
+
silent_cancellers = test_ctx.fixtures_with_cancel - test_ctx.fixtures_with_errors
|
170
|
+
|
171
|
+
if silent_cancellers:
|
172
|
+
for fixture in silent_cancellers:
|
173
|
+
test_ctx.error_list.append(
|
174
|
+
RuntimeError(f"{fixture.name} cancelled the test but didn't raise an error"),
|
175
|
+
)
|
176
|
+
|
177
|
+
if len(test_ctx.error_list) == 1:
|
178
|
+
raise test_ctx.error_list[0]
|
179
|
+
elif test_ctx.error_list:
|
180
|
+
raise BaseExceptionGroup('errors in async test and async fixtures', test_ctx.error_list)
|
181
|
+
|
182
|
+
return _bootstrap_fixtures_and_run_test
|
@@ -0,0 +1,10 @@
|
|
1
|
+
import inspect
|
2
|
+
import typing as ta
|
3
|
+
|
4
|
+
|
5
|
+
def is_coroutine_function(func: ta.Any) -> bool:
|
6
|
+
return inspect.iscoroutinefunction(func) or getattr(func, '_is_coroutine', False)
|
7
|
+
|
8
|
+
|
9
|
+
def is_async_function(func: ta.Any) -> bool:
|
10
|
+
return is_coroutine_function(func) or inspect.isasyncgenfunction(func)
|
@@ -17,22 +17,8 @@ class ManagerMark(lang.Abstract):
|
|
17
17
|
raise NotImplementedError
|
18
18
|
|
19
19
|
|
20
|
-
def _deep_subclasses(cls):
|
21
|
-
ret = set()
|
22
|
-
|
23
|
-
def rec(cur):
|
24
|
-
for nxt in cur.__subclasses__():
|
25
|
-
if nxt not in ret:
|
26
|
-
ret.add(nxt)
|
27
|
-
rec(nxt)
|
28
|
-
|
29
|
-
rec(cls)
|
30
|
-
return ret
|
31
|
-
|
32
|
-
|
33
20
|
@register
|
34
21
|
class ManagerMarksPlugin:
|
35
|
-
|
36
22
|
@lang.cached_function
|
37
23
|
def mark_classes(self) -> ta.Mapping[str, type[ManagerMark]]:
|
38
24
|
return {
|
omlish/text/indent.py
CHANGED
omlish/text/minja.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: omlish
|
3
|
-
Version: 0.0.0.
|
3
|
+
Version: 0.0.0.dev197
|
4
4
|
Summary: omlish
|
5
5
|
Author: wrmsr
|
6
6
|
License: BSD-3-Clause
|
@@ -13,7 +13,7 @@ Classifier: Operating System :: POSIX
|
|
13
13
|
Requires-Python: >=3.12
|
14
14
|
License-File: LICENSE
|
15
15
|
Provides-Extra: all
|
16
|
-
Requires-Dist: anyio~=4.
|
16
|
+
Requires-Dist: anyio~=4.8; extra == "all"
|
17
17
|
Requires-Dist: sniffio~=1.3; extra == "all"
|
18
18
|
Requires-Dist: greenlet~=3.1; extra == "all"
|
19
19
|
Requires-Dist: trio~=0.27; extra == "all"
|
@@ -44,7 +44,7 @@ Requires-Dist: apsw~=3.47; extra == "all"
|
|
44
44
|
Requires-Dist: sqlean.py~=3.45; extra == "all"
|
45
45
|
Requires-Dist: duckdb~=1.1; extra == "all"
|
46
46
|
Requires-Dist: pytest~=8.0; extra == "all"
|
47
|
-
Requires-Dist: anyio~=4.
|
47
|
+
Requires-Dist: anyio~=4.8; extra == "all"
|
48
48
|
Requires-Dist: sniffio~=1.3; extra == "all"
|
49
49
|
Requires-Dist: asttokens~=3.0; extra == "all"
|
50
50
|
Requires-Dist: executing~=2.1; extra == "all"
|
@@ -52,7 +52,7 @@ Requires-Dist: orjson~=3.10; extra == "all"
|
|
52
52
|
Requires-Dist: pyyaml~=6.0; extra == "all"
|
53
53
|
Requires-Dist: wrapt~=1.14; extra == "all"
|
54
54
|
Provides-Extra: async
|
55
|
-
Requires-Dist: anyio~=4.
|
55
|
+
Requires-Dist: anyio~=4.8; extra == "async"
|
56
56
|
Requires-Dist: sniffio~=1.3; extra == "async"
|
57
57
|
Requires-Dist: greenlet~=3.1; extra == "async"
|
58
58
|
Requires-Dist: trio~=0.27; extra == "async"
|
@@ -93,7 +93,7 @@ Requires-Dist: duckdb~=1.1; extra == "sqldrivers"
|
|
93
93
|
Provides-Extra: testing
|
94
94
|
Requires-Dist: pytest~=8.0; extra == "testing"
|
95
95
|
Provides-Extra: plus
|
96
|
-
Requires-Dist: anyio~=4.
|
96
|
+
Requires-Dist: anyio~=4.8; extra == "plus"
|
97
97
|
Requires-Dist: sniffio~=1.3; extra == "plus"
|
98
98
|
Requires-Dist: asttokens~=3.0; extra == "plus"
|
99
99
|
Requires-Dist: executing~=2.1; extra == "plus"
|
@@ -1,5 +1,5 @@
|
|
1
1
|
omlish/.manifests.json,sha256=dyIpveH7Z8OnQp2pTn6NVv7LCDXVrozJWAzbk8PBavg,7950
|
2
|
-
omlish/__about__.py,sha256=
|
2
|
+
omlish/__about__.py,sha256=tOVu5niNIXFKxmAD9pNMz4UGHVFnBkHV49gAq25Z_xk,3409
|
3
3
|
omlish/__init__.py,sha256=SsyiITTuK0v74XpKV8dqNaCmjOlan1JZKrHQv5rWKPA,253
|
4
4
|
omlish/c3.py,sha256=ubu7lHwss5V4UznbejAI0qXhXahrU01MysuHOZI9C4U,8116
|
5
5
|
omlish/cached.py,sha256=UI-XTFBwA6YXWJJJeBn-WkwBkfzDjLBBaZf4nIJA9y0,510
|
@@ -8,7 +8,7 @@ omlish/datetimes.py,sha256=HajeM1kBvwlTa-uR1TTZHmZ3zTPnnUr1uGGQhiO1XQ0,2152
|
|
8
8
|
omlish/defs.py,sha256=9uUjJuVIbCBL3g14fyzAp-9gH935MFofvlfOGwcBIaM,4913
|
9
9
|
omlish/dynamic.py,sha256=35C_cCX_Vq2HrHzGk5T-zbrMvmUdiIiwDzDNixczoDo,6541
|
10
10
|
omlish/libc.py,sha256=8r7Ejyhttk9ruCfBkxNTrlzir5WPbDE2vmY7VPlceMA,15362
|
11
|
-
omlish/
|
11
|
+
omlish/outcome.py,sha256=ABIE0zjjTyTNtn-ZqQ_9_mUzLiBQ3sDAyqc9JVD8N2k,7852
|
12
12
|
omlish/runmodule.py,sha256=PWvuAaJ9wQQn6bx9ftEL3_d04DyotNn8dR_twm2pgw0,700
|
13
13
|
omlish/shlex.py,sha256=bsW2XUD8GiMTUTDefJejZ5AyqT1pTgWMPD0BMoF02jE,248
|
14
14
|
omlish/subprocesses.py,sha256=KOvt5gvpq2uisjYKyU_XUPZyM6yq8ywgbfWjz-lx9CQ,8686
|
@@ -88,13 +88,13 @@ omlish/asyncs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
88
88
|
omlish/asyncs/all.py,sha256=uUz9ziKh4_QrgmdhKFMgq6j7mFbiZd3LiogguDCQsGI,587
|
89
89
|
omlish/asyncs/anyio.py,sha256=gfpx-D8QGmUfhnQxHEaHXcAP8zSMQjcGw4COFTGNnHI,8021
|
90
90
|
omlish/asyncs/asyncs.py,sha256=Tf7ZodTGepkM7HAuFcDNh9lLzzrMw6rELWvopGmFkh4,2035
|
91
|
-
omlish/asyncs/bridge.py,sha256=
|
91
|
+
omlish/asyncs/bridge.py,sha256=zVAhbFVDvw3qJjcvOKKY2mI8AwrmcmddKsW9KIzPdLI,9740
|
92
92
|
omlish/asyncs/flavors.py,sha256=1mNxGNRVmjUHzA13K5ht8vdJv4CLEmzYTQ6BZXr1520,4866
|
93
93
|
omlish/asyncs/trio.py,sha256=fmZ5b_lKdVV8NQ3euCUutWgnkqTFzSnOjvJSA_jvmrE,367
|
94
94
|
omlish/asyncs/trio_asyncio.py,sha256=oqdOHy0slj9PjVxaDf3gJkq9AAgg7wYZbB469jOftVw,1327
|
95
95
|
omlish/asyncs/asyncio/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
96
|
-
omlish/asyncs/asyncio/all.py,sha256=
|
97
|
-
omlish/asyncs/asyncio/asyncio.py,sha256=
|
96
|
+
omlish/asyncs/asyncio/all.py,sha256=eZDtL8atzHqIdGCAAcQYWVmNvgRYerJB9Sy0reh-09k,115
|
97
|
+
omlish/asyncs/asyncio/asyncio.py,sha256=fvIc3M01Bo_qZTFz3Z2X7NrXC_9DnS0vtZKizGiV034,830
|
98
98
|
omlish/asyncs/asyncio/channels.py,sha256=ZbmsEmdK1fV96liHdcVpRqA2dAMkXJt4Q3rFAg3YOIw,1074
|
99
99
|
omlish/asyncs/asyncio/streams.py,sha256=Uc9PCWSfBqrK2kdVtfjjQU1eaYTWYmZm8QISDj2xiuw,1004
|
100
100
|
omlish/asyncs/asyncio/subprocesses.py,sha256=XlIWwSxpVB7sMVc75-f7dI6r08JkdipNFRWXUKS8zAw,6960
|
@@ -106,7 +106,7 @@ omlish/asyncs/bluelet/api.py,sha256=yeM5SauiIbvKj26mDdxn5mOj8s5fFIw2xBSe-P6HVC0,
|
|
106
106
|
omlish/asyncs/bluelet/core.py,sha256=NpGQhb865aeXPKV_67l-6FiuQzdDJJ85zjfvCR5R8Pc,5430
|
107
107
|
omlish/asyncs/bluelet/events.py,sha256=iXpRWmy64YcshT_nuyiJ39jbketZdtj8LrdlX3JmpoY,2440
|
108
108
|
omlish/asyncs/bluelet/files.py,sha256=pgcLV_3oGbpqQmOrii8SeizyYLp8XKofQJhqM82RlKw,2389
|
109
|
-
omlish/asyncs/bluelet/runner.py,sha256=
|
109
|
+
omlish/asyncs/bluelet/runner.py,sha256=F6Ep0th09f-FkIRJfMN3_u-iG21jNNv11WyqnHyITYU,15475
|
110
110
|
omlish/asyncs/bluelet/sockets.py,sha256=RrC2vU52dOEBYKzvoh1qA39uUE8p3uCB_oxnhaP1AeA,6752
|
111
111
|
omlish/bootstrap/__init__.py,sha256=-Rtsg7uPQNhh1dIT9nqrz96XlqizwoLnWf-FwOEstJI,730
|
112
112
|
omlish/bootstrap/__main__.py,sha256=4jCwsaogp0FrJjJZ85hzF4-WqluPeheHbfeoKynKvNs,194
|
@@ -117,13 +117,13 @@ omlish/bootstrap/main.py,sha256=yZhOHDDlj4xB5a89dRdT8z58FsqqnpoBg1-tvY2CJe4,5903
|
|
117
117
|
omlish/bootstrap/marshal.py,sha256=ZxdAeMNd2qXRZ1HUK89HmEhz8tqlS9OduW34QBscKw0,516
|
118
118
|
omlish/bootstrap/sys.py,sha256=aqMzxZa_lPj78cgz4guYZAkjT6En32e2LptfEo20NIM,8769
|
119
119
|
omlish/codecs/__init__.py,sha256=-FDwRJFGagg-fZyQ8wup4GPuR6gHpmaChzthlykn-kY,876
|
120
|
-
omlish/codecs/base.py,sha256=
|
120
|
+
omlish/codecs/base.py,sha256=uFrDvP7SZdeBbpuUzGHvyOdFNAmhjkBG2cVaVydRsjw,2221
|
121
121
|
omlish/codecs/bytes.py,sha256=jlZ87OmZ52HhQDNyL87R3OIviK2qV5iU2jZYOTOLWjk,2157
|
122
122
|
omlish/codecs/chain.py,sha256=DrBi5vbaFfObfoppo6alwOmyW2XbrH2051cjExwr2Gs,527
|
123
123
|
omlish/codecs/funcs.py,sha256=p4imNt7TobyZVXWC-WhntHVu9KfJrO4QwdtPRh-cVOk,850
|
124
124
|
omlish/codecs/registry.py,sha256=8ySUG-kwGJoUN1HCRnz8VjcykB0wlIzoWF5WTAE1ny0,3860
|
125
125
|
omlish/codecs/standard.py,sha256=eiZ4u9ep0XrA4Z_D1zJI0vmWyuN8HLrX4Se_r_Cq_ZM,60
|
126
|
-
omlish/codecs/text.py,sha256=
|
126
|
+
omlish/codecs/text.py,sha256=JzrdwMpQPo2NBBg3K1EZszzQy5vEWmd82SIerJd4yeQ,5723
|
127
127
|
omlish/collections/__init__.py,sha256=zeUvcAz073ekko37QKya6sElTMfKTuF1bKrdbMtaRpI,2142
|
128
128
|
omlish/collections/abc.py,sha256=sP7BpTVhx6s6C59mTFeosBi4rHOWC6tbFBYbxdZmvh0,2365
|
129
129
|
omlish/collections/coerce.py,sha256=g68ROb_-5HgH-vI8612mU2S0FZ8-wp2ZHK5_Zy_kVC0,7037
|
@@ -329,27 +329,27 @@ omlish/io/pyio.py,sha256=q4RBFVpBE5PYjnGPGT-_4pcZb7dFJmLJ4LtI8OoDRQY,95433
|
|
329
329
|
omlish/io/trampoline.py,sha256=oUKTQg1F5xQS1431Kt7MbK-NZpX509ubcXU-s86xJr8,7171
|
330
330
|
omlish/io/compress/__init__.py,sha256=qV-aDfPWykTMYcoQmE8THZ4KFDRzqwN3QPPNEJVarXY,86
|
331
331
|
omlish/io/compress/abc.py,sha256=P9YoQX8XYoq2UfBsinKLUuwwqV1ODUIJzjTraRWGF1M,3090
|
332
|
-
omlish/io/compress/adapters.py,sha256=
|
333
|
-
omlish/io/compress/base.py,sha256=
|
332
|
+
omlish/io/compress/adapters.py,sha256=LJHhjwMHXstoLyX_q0QhGoBAcqyYGWfzhzQbGBXHzHY,6148
|
333
|
+
omlish/io/compress/base.py,sha256=zwPnicyrEY-zersxdhxGHXxn02ycl8ew2uZXEecJea4,615
|
334
334
|
omlish/io/compress/brotli.py,sha256=Q2t9uRqBEgRyJCSPsTaJv5w7d-rhsjDMluA4VRBHa_A,1182
|
335
|
-
omlish/io/compress/bz2.py,sha256=
|
336
|
-
omlish/io/compress/codecs.py,sha256=
|
337
|
-
omlish/io/compress/gzip.py,sha256=
|
338
|
-
omlish/io/compress/lz4.py,sha256=
|
339
|
-
omlish/io/compress/lzma.py,sha256=
|
335
|
+
omlish/io/compress/bz2.py,sha256=HtwBuBYHJ3MyWO9xJ0XhWpyIYTA3OszLrpu_J4kRRPA,1534
|
336
|
+
omlish/io/compress/codecs.py,sha256=VBc_MAz0W8lVKTKavot3aVKOuPmEUquzarMtpyuteiU,1804
|
337
|
+
omlish/io/compress/gzip.py,sha256=tSjZmLWc7BZugYhmv07Pjr_TaVD1X-0JnZIlAk67iyQ,12213
|
338
|
+
omlish/io/compress/lz4.py,sha256=qaze1yVXexjJyN18Adh8fbTm_5pEeyytx66KoMUNpCU,2759
|
339
|
+
omlish/io/compress/lzma.py,sha256=qDyshBgBUSPcZpAyXiRXnqI7zx7x60UpPxn8K3nN8aM,2469
|
340
340
|
omlish/io/compress/snappy.py,sha256=JFoH_9l0Tr9AGaQ0jHRiP4TsFnG071l27mprCBcqt4c,704
|
341
|
-
omlish/io/compress/zlib.py,sha256=
|
341
|
+
omlish/io/compress/zlib.py,sha256=dE38zBY4qNihUYtPjSpNRXweiw6mB6xsYqsBJklTDXM,2364
|
342
342
|
omlish/io/compress/zstd.py,sha256=wik_HWLq_8fGAJgGyMGq9fhFQovot1aCH4lwMpihQmg,949
|
343
|
+
omlish/io/coro/__init__.py,sha256=cfeng1ESiMlCU_ubI1aWcBD9IK0Im7emOTsggmlEjtI,1046
|
344
|
+
omlish/io/coro/consts.py,sha256=4r6IMLBMic6MJHVn9UiORIkkPAuxsqtzFT3KV0fatC0,33
|
345
|
+
omlish/io/coro/direct.py,sha256=Y--rP3wvBAYMeYctokb5IGd8UyQGmEFChyKISmRg5k0,294
|
346
|
+
omlish/io/coro/readers.py,sha256=9VcXuBQ7BSoFen8UVuYFwnl2jJVjyilWV7QeqLNQtKU,4131
|
347
|
+
omlish/io/coro/stepped.py,sha256=eAppRniUZ00rk3goWLU4zsd52MhZB2_YrOmFqs3RfR4,4929
|
343
348
|
omlish/io/fdio/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
|
344
349
|
omlish/io/fdio/handlers.py,sha256=VDPEff3yXPnCj2jZEkrzuI42bKC8wD8fLmOG97hKrgo,1350
|
345
350
|
omlish/io/fdio/kqueue.py,sha256=YgGBQibkAUYODYDiGl7Enjtx1oQsJXuDsBLBXgqlLQw,3832
|
346
351
|
omlish/io/fdio/manager.py,sha256=q4wWf7nKrNtjx6yPEvrVnFt4UtK_BTvVlquEGw7poEo,1250
|
347
352
|
omlish/io/fdio/pollers.py,sha256=yNadAt3W5wd90PFmd3vD77bq5QwoVb2A6SM2JjZpKRs,5507
|
348
|
-
omlish/io/generators/__init__.py,sha256=YsSLJY9uw72eX3iXd_A0pM69g7EvEqMFdCdR_BBD4RA,1216
|
349
|
-
omlish/io/generators/consts.py,sha256=4r6IMLBMic6MJHVn9UiORIkkPAuxsqtzFT3KV0fatC0,33
|
350
|
-
omlish/io/generators/direct.py,sha256=A9VJB1rNKU3l-NatpYIwyCLI3R_ybGglmdx6sAtoTo4,324
|
351
|
-
omlish/io/generators/readers.py,sha256=MolTFCzcnD5XoP0su0YUNHJ0xlHC3KTihvWAi75y8Bo,4336
|
352
|
-
omlish/io/generators/stepped.py,sha256=WZnLpCzv5pA6jLdb1lplXoKRPbREw9wO586Dew5EzV4,5129
|
353
353
|
omlish/iterators/__init__.py,sha256=yMavf5FofiS1EU4UFuWPXiFZ03W0H-y7MuMxW8FUaEE,358
|
354
354
|
omlish/iterators/iterators.py,sha256=ghI4dO6WPyyFOLTIIMaHQ_IOy2xXaFpGPqveZ5YGIBU,3158
|
355
355
|
omlish/iterators/recipes.py,sha256=53mkexitMhkwXQZbL6DrhpT0WePQ_56uXd5Jaw3DfzI,467
|
@@ -457,8 +457,12 @@ omlish/math/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
457
457
|
omlish/math/bits.py,sha256=yip1l8agOYzT7bFyMGc0RR3XlnGCfHMpjw_SECLLh1I,3477
|
458
458
|
omlish/math/floats.py,sha256=UimhOT7KRl8LXTzOI5cQWoX_9h6WNWe_3vcOuO7-h_8,327
|
459
459
|
omlish/math/stats.py,sha256=MegzKVsmv2kra4jDWLOUgV0X7Ee2Tbl5u6ql1v4-dEY,10053
|
460
|
+
omlish/multiprocessing/__init__.py,sha256=hFAym2y_ws4JUMiB216J45LDajrlnfAqsTq214gvHFc,588
|
461
|
+
omlish/multiprocessing/death.py,sha256=_JV88yxwYIalamIMuqmGTQ4KYd0t-UHLjVkdoliPWL8,2943
|
462
|
+
omlish/multiprocessing/proxies.py,sha256=bInhGds2rv6xT9q3qRMlZuSXFAjwfspkiohXZ36aUpY,484
|
463
|
+
omlish/multiprocessing/spawn.py,sha256=sTvPLIJGYnjjI6ASqhFzHF-97tCnaOXX7u7s-33SUMw,1875
|
460
464
|
omlish/os/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
461
|
-
omlish/os/atomics.py,sha256=
|
465
|
+
omlish/os/atomics.py,sha256=KhWNeh4mzU3M-TF0v8uR6hUqMfZJW42MeyIK9Jl6R0k,5246
|
462
466
|
omlish/os/deathsig.py,sha256=hk9Yq2kyDdI-cI7OQH7mOfpRbOKzY_TfPKEqgrjVYbA,641
|
463
467
|
omlish/os/files.py,sha256=1tNy1z5I_CgYKA5c6lOfsXc-hknP4tQDbSShdz8HArw,1308
|
464
468
|
omlish/os/journald.py,sha256=2nI8Res1poXkbLc31--MPUlzYMESnCcPUkIxDOCjZW0,3903
|
@@ -482,7 +486,7 @@ omlish/secrets/subprocesses.py,sha256=ffjfbgPbEE_Pwb_87vG4yYR2CGZy3I31mHNCo_0JtH
|
|
482
486
|
omlish/sockets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
483
487
|
omlish/sockets/addresses.py,sha256=ZQFacDsXo6cKSgEjzN525IcUJPyfubXETzbY-_BBAro,1285
|
484
488
|
omlish/sockets/handlers.py,sha256=9kkNMj1DTJa4xo_3hcBvSkjKc-dy_Ho5he2ubJieJ2A,621
|
485
|
-
omlish/sockets/server.py,sha256=
|
489
|
+
omlish/sockets/server.py,sha256=96vCNBvHSf8lWI3kd3RBbY0M2qXGaD_TksMhnBQ0_q0,1600
|
486
490
|
omlish/specs/__init__.py,sha256=zZwF8yXTEkSstYtORkDhVLK-_hWU8WOJCuBpognb_NY,118
|
487
491
|
omlish/specs/jmespath/LICENSE,sha256=IH-ZZlZkS8XMkf_ubNVD1aYHQ2l_wd0tmHtXrCcYpRU,1113
|
488
492
|
omlish/specs/jmespath/__init__.py,sha256=9tsrquw1kXe1KAhTP3WeL0GlGBiTguQVxsC-lUYTWP4,2087
|
@@ -566,38 +570,46 @@ omlish/term/progressbar.py,sha256=TiwdmPSMa5jQj35i1NQURTWQGy4eWUNx_XiPM38JtvQ,31
|
|
566
570
|
omlish/term/vt100/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
567
571
|
omlish/term/vt100/c.py,sha256=cAhDKXI81PZRtFmTotfad3HZGREP1QnOlWYoAw6v-Fw,3532
|
568
572
|
omlish/term/vt100/states.py,sha256=OxPUxfFTcfz56MhtDgIigEApChOtN6XO1g6R2H08mu4,8303
|
569
|
-
omlish/term/vt100/terminal.py,sha256=
|
573
|
+
omlish/term/vt100/terminal.py,sha256=KUlg331ele7P6SHsBKdbpdQFDKsxSply1Ds27NkppTs,9359
|
570
574
|
omlish/testing/__init__.py,sha256=M_BQrcCHkoL-ZvE-UpQ8XxXNYRRawhjUz4rCJnAqM2A,152
|
571
575
|
omlish/testing/testing.py,sha256=TT2wwSzPZ_KhIvKxpM1qc1yHKD-LHDNgGrcr_h8vs7c,2895
|
572
|
-
omlish/testing/pytest/__init__.py,sha256=
|
576
|
+
omlish/testing/pytest/__init__.py,sha256=rOpQYgp7jYjEIMjInzl-a_uIMqmOtVwGzDgJyCDpvxg,206
|
573
577
|
omlish/testing/pytest/helpers.py,sha256=TJpD60mBtLi9FtxX4TThfuXvg5FIRPSiZk1aeRwe-D4,197
|
574
|
-
omlish/testing/pytest/marks.py,sha256=4-3WgunN_fcmhkmQ6mtX_AFo5QRDwflNSH7NoyoXui4,432
|
575
578
|
omlish/testing/pytest/skip.py,sha256=NxTkAQiS3HKZR3sfFdxOR2LCFwtCveY6Ap-qtexiZbw,839
|
576
579
|
omlish/testing/pytest/inject/__init__.py,sha256=pdRKv1HcDmJ_yArKJbYITPXXZthRSGgBJWqITr0Er38,117
|
577
580
|
omlish/testing/pytest/inject/harness.py,sha256=_Qf7lLcYc_dpauYOE68u_a65jPCFWmQUYv9m_OOdNqs,5724
|
578
581
|
omlish/testing/pytest/plugins/__init__.py,sha256=ys1zXrYrNm7Uo6YOIVJ6Bd3dQo6kv387k7MbTYlqZSI,467
|
579
582
|
omlish/testing/pytest/plugins/_registry.py,sha256=IK04KlBgiOJxKAyCCgjpX2R-9tE-btalYJkgjLc8Te8,77
|
580
|
-
omlish/testing/pytest/plugins/asyncs.py,sha256=CG-cWWxCtxVIyKJKEjxfFV0MVwYBHPo1mb-umCGz9X8,5532
|
581
583
|
omlish/testing/pytest/plugins/depskip.py,sha256=xithY-OMtjwhv8mcRNkv-WI_PSQtHldQ8H1s60MIXkk,2673
|
582
584
|
omlish/testing/pytest/plugins/logging.py,sha256=Y1I_3DiiuDSynObkm8bNPZxdvljUWXbqD6YUM5uI34o,391
|
583
|
-
omlish/testing/pytest/plugins/managermarks.py,sha256=
|
585
|
+
omlish/testing/pytest/plugins/managermarks.py,sha256=IzkspjT8-ToPIlHZs9cHt6RYbm51poJLjYVvkFPbJhE,1300
|
584
586
|
omlish/testing/pytest/plugins/pydevd.py,sha256=AXtN83M39ZKJ4VH3MJEhvPnAmYzD5u1r8ehz-0om50Q,842
|
585
587
|
omlish/testing/pytest/plugins/repeat.py,sha256=flSQzE9GFOWksVKz-mUGnpxJpv3yRqn1G4K8pW7JHs0,498
|
586
588
|
omlish/testing/pytest/plugins/skips.py,sha256=EoZDg1uWccgbAegmzqI85c7RliycD1e2J4Y7vfDRhwM,1041
|
587
589
|
omlish/testing/pytest/plugins/spacing.py,sha256=JQQhi9q3c523Ro1a_K_9RGAb7HotiO74N8bYX2VESFE,707
|
588
590
|
omlish/testing/pytest/plugins/switches.py,sha256=CflHe6gLhkLt_9OcAmzskuZsrhZhwOuL_bIdogibARc,3815
|
589
591
|
omlish/testing/pytest/plugins/utils.py,sha256=L5C622UXcA_AUKDcvyh5IMiRfqSGGz0McdhwZWvfMlU,261
|
592
|
+
omlish/testing/pytest/plugins/asyncs/__init__.py,sha256=TTNhFmP_krug1973sq_bpWBTIvg68-1nbuVLSs92Z6k,41
|
593
|
+
omlish/testing/pytest/plugins/asyncs/consts.py,sha256=0NOCkzV43dOu3u97BqYMQ4mPG8JuFncpWibkOZpCqX4,55
|
594
|
+
omlish/testing/pytest/plugins/asyncs/fixtures.py,sha256=HyhtZLq5Qai7pS9Z4Ejl0f0NyVtDjJJL9fhbUKVUx2M,11299
|
595
|
+
omlish/testing/pytest/plugins/asyncs/plugin.py,sha256=-gVLHZb78nEfMOnmWKY0gdT3BOHjY3bp-GnBGshOvPo,6021
|
596
|
+
omlish/testing/pytest/plugins/asyncs/utils.py,sha256=K-nQxSJQL-3N_xtLqfCX11KSLYCG_gPQ6hZqLQZIHNQ,294
|
597
|
+
omlish/testing/pytest/plugins/asyncs/backends/__init__.py,sha256=DpJGt5KA2N2pNXy59raVyJH1969M1AP80pJAqIlNEAs,359
|
598
|
+
omlish/testing/pytest/plugins/asyncs/backends/asyncio.py,sha256=0b8pmbXNW2qI8qo1ARxpONdqw8DWf0v5J2-9mkM9hrc,820
|
599
|
+
omlish/testing/pytest/plugins/asyncs/backends/base.py,sha256=fTZ6R_iKpAp-8DVw8js8rxC_VNqj6onFD4KKBWnmtXk,587
|
600
|
+
omlish/testing/pytest/plugins/asyncs/backends/trio.py,sha256=xty9TR7-Kk6n0cdOqErLilPLLCchJe6zmEyhpypTmKM,3330
|
601
|
+
omlish/testing/pytest/plugins/asyncs/backends/trio_asyncio.py,sha256=VcGVwf4V-1ZFK_70FrFS9b11EU1dOy1ozhhIDXGNSEo,3169
|
590
602
|
omlish/text/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
591
603
|
omlish/text/asdl.py,sha256=AS3irh-sag5pqyH3beJif78PjCbOaFso1NeKq-HXuTs,16867
|
592
604
|
omlish/text/delimit.py,sha256=ubPXcXQmtbOVrUsNh5gH1mDq5H-n1y2R4cPL5_DQf68,4928
|
593
605
|
omlish/text/glyphsplit.py,sha256=kqqjglRdxGo0czYZxOz9Vi8aBmVsCOq8h6lPwRA5xe0,3803
|
594
|
-
omlish/text/indent.py,sha256=
|
595
|
-
omlish/text/minja.py,sha256=
|
606
|
+
omlish/text/indent.py,sha256=YjtJEBYWuk8--b9JU_T6q4yxV85_TR7VEVr5ViRCFwk,1336
|
607
|
+
omlish/text/minja.py,sha256=jZC-fp3Xuhx48ppqsf2Sf1pHbC0t8XBB7UpUUoOk2Qw,5751
|
596
608
|
omlish/text/parts.py,sha256=7vPF1aTZdvLVYJ4EwBZVzRSy8XB3YqPd7JwEnNGGAOo,6495
|
597
609
|
omlish/text/random.py,sha256=jNWpqiaKjKyTdMXC-pWAsSC10AAP-cmRRPVhm59ZWLk,194
|
598
|
-
omlish-0.0.0.
|
599
|
-
omlish-0.0.0.
|
600
|
-
omlish-0.0.0.
|
601
|
-
omlish-0.0.0.
|
602
|
-
omlish-0.0.0.
|
603
|
-
omlish-0.0.0.
|
610
|
+
omlish-0.0.0.dev197.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
|
611
|
+
omlish-0.0.0.dev197.dist-info/METADATA,sha256=MjEjDgFhD7eg4RDWvX9ippECV4KjRVf8CoCIoRt2Wik,4264
|
612
|
+
omlish-0.0.0.dev197.dist-info/WHEEL,sha256=A3WOREP4zgxI0fKrHUG8DC8013e3dK3n7a6HDbcEIwE,91
|
613
|
+
omlish-0.0.0.dev197.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
|
614
|
+
omlish-0.0.0.dev197.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
|
615
|
+
omlish-0.0.0.dev197.dist-info/RECORD,,
|
omlish/io/generators/__init__.py
DELETED
@@ -1,56 +0,0 @@
|
|
1
|
-
from .consts import ( # noqa
|
2
|
-
DEFAULT_BUFFER_SIZE,
|
3
|
-
)
|
4
|
-
|
5
|
-
from .direct import ( # noqa
|
6
|
-
DirectGenerator,
|
7
|
-
|
8
|
-
BytesDirectGenerator,
|
9
|
-
StrDirectGenerator,
|
10
|
-
)
|
11
|
-
|
12
|
-
from .readers import ( # noqa
|
13
|
-
ReaderGenerator,
|
14
|
-
BytesReaderGenerator,
|
15
|
-
StrReaderGenerator,
|
16
|
-
|
17
|
-
ExactReaderGenerator,
|
18
|
-
BytesExactReaderGenerator,
|
19
|
-
StrExactReaderGenerator,
|
20
|
-
|
21
|
-
GeneratorReader,
|
22
|
-
|
23
|
-
PrependableGeneratorReader,
|
24
|
-
PrependableBytesGeneratorReader,
|
25
|
-
PrependableStrGeneratorReader,
|
26
|
-
prependable_bytes_generator_reader,
|
27
|
-
prependable_str_generator_reader,
|
28
|
-
|
29
|
-
BufferedGeneratorReader,
|
30
|
-
BufferedBytesGeneratorReader,
|
31
|
-
BufferedStrGeneratorReader,
|
32
|
-
buffered_bytes_generator_reader,
|
33
|
-
buffered_str_generator_reader,
|
34
|
-
)
|
35
|
-
|
36
|
-
from .stepped import ( # noqa
|
37
|
-
SteppedGenerator,
|
38
|
-
BytesSteppedGenerator,
|
39
|
-
StrSteppedGenerator,
|
40
|
-
BytesToStrSteppedGenerator,
|
41
|
-
StrToBytesSteppedGenerator,
|
42
|
-
|
43
|
-
SteppedReaderGenerator,
|
44
|
-
BytesSteppedReaderGenerator,
|
45
|
-
StrSteppedReaderGenerator,
|
46
|
-
|
47
|
-
flatmap_stepped_generator,
|
48
|
-
|
49
|
-
joined_bytes_stepped_generator,
|
50
|
-
joined_str_stepped_generator,
|
51
|
-
|
52
|
-
read_into_bytes_stepped_generator,
|
53
|
-
read_into_str_stepped_generator,
|
54
|
-
|
55
|
-
buffer_bytes_stepped_reader_generator,
|
56
|
-
)
|
omlish/io/generators/direct.py
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
import typing as ta
|
2
|
-
|
3
|
-
|
4
|
-
O = ta.TypeVar('O')
|
5
|
-
I = ta.TypeVar('I')
|
6
|
-
R = ta.TypeVar('R')
|
7
|
-
|
8
|
-
|
9
|
-
# Direct generators yield outputs 1:1 with inputs.
|
10
|
-
DirectGenerator: ta.TypeAlias = ta.Generator[O, I, R]
|
11
|
-
|
12
|
-
BytesDirectGenerator: ta.TypeAlias = DirectGenerator[bytes, bytes, R]
|
13
|
-
StrDirectGenerator: ta.TypeAlias = DirectGenerator[str, str, R]
|
omlish/testing/pytest/marks.py
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
import typing as ta
|
2
|
-
|
3
|
-
import pytest
|
4
|
-
|
5
|
-
from ... import lang # noqa
|
6
|
-
from .plugins.managermarks import ManagerMark # noqa
|
7
|
-
|
8
|
-
|
9
|
-
if ta.TYPE_CHECKING:
|
10
|
-
from ...asyncs.asyncio import all as aiu
|
11
|
-
else:
|
12
|
-
aiu = lang.proxy_import('...asyncs.asyncio.all', __package__)
|
13
|
-
|
14
|
-
|
15
|
-
class drain_asyncio(ManagerMark): # noqa
|
16
|
-
def __call__(self, item: pytest.Function) -> ta.Iterator[None]:
|
17
|
-
with aiu.draining_asyncio_tasks():
|
18
|
-
yield
|