pytest-asyncio-concurrent 0.2.0__tar.gz → 0.2.2__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.
- {pytest_asyncio_concurrent-0.2.0/pytest_asyncio_concurrent.egg-info → pytest_asyncio_concurrent-0.2.2}/PKG-INFO +2 -2
- {pytest_asyncio_concurrent-0.2.0 → pytest_asyncio_concurrent-0.2.2}/pyproject.toml +2 -2
- {pytest_asyncio_concurrent-0.2.0 → pytest_asyncio_concurrent-0.2.2}/pytest_asyncio_concurrent/plugin.py +88 -52
- {pytest_asyncio_concurrent-0.2.0 → pytest_asyncio_concurrent-0.2.2/pytest_asyncio_concurrent.egg-info}/PKG-INFO +2 -2
- {pytest_asyncio_concurrent-0.2.0 → pytest_asyncio_concurrent-0.2.2}/LICENSE +0 -0
- {pytest_asyncio_concurrent-0.2.0 → pytest_asyncio_concurrent-0.2.2}/README.rst +0 -0
- {pytest_asyncio_concurrent-0.2.0 → pytest_asyncio_concurrent-0.2.2}/pytest_asyncio_concurrent/__init__.py +0 -0
- {pytest_asyncio_concurrent-0.2.0 → pytest_asyncio_concurrent-0.2.2}/pytest_asyncio_concurrent/fixture_async.py +0 -0
- {pytest_asyncio_concurrent-0.2.0 → pytest_asyncio_concurrent-0.2.2}/pytest_asyncio_concurrent/grouping.py +0 -0
- {pytest_asyncio_concurrent-0.2.0 → pytest_asyncio_concurrent-0.2.2}/pytest_asyncio_concurrent/hooks.py +0 -0
- {pytest_asyncio_concurrent-0.2.0 → pytest_asyncio_concurrent-0.2.2}/pytest_asyncio_concurrent.egg-info/SOURCES.txt +0 -0
- {pytest_asyncio_concurrent-0.2.0 → pytest_asyncio_concurrent-0.2.2}/pytest_asyncio_concurrent.egg-info/dependency_links.txt +0 -0
- {pytest_asyncio_concurrent-0.2.0 → pytest_asyncio_concurrent-0.2.2}/pytest_asyncio_concurrent.egg-info/entry_points.txt +0 -0
- {pytest_asyncio_concurrent-0.2.0 → pytest_asyncio_concurrent-0.2.2}/pytest_asyncio_concurrent.egg-info/requires.txt +0 -0
- {pytest_asyncio_concurrent-0.2.0 → pytest_asyncio_concurrent-0.2.2}/pytest_asyncio_concurrent.egg-info/top_level.txt +0 -0
- {pytest_asyncio_concurrent-0.2.0 → pytest_asyncio_concurrent-0.2.2}/setup.cfg +0 -0
- {pytest_asyncio_concurrent-0.2.0 → pytest_asyncio_concurrent-0.2.2}/tests/test_async_fixture.py +0 -0
- {pytest_asyncio_concurrent-0.2.0 → pytest_asyncio_concurrent-0.2.2}/tests/test_compatibility.py +0 -0
- {pytest_asyncio_concurrent-0.2.0 → pytest_asyncio_concurrent-0.2.2}/tests/test_error.py +0 -0
- {pytest_asyncio_concurrent-0.2.0 → pytest_asyncio_concurrent-0.2.2}/tests/test_fixture_lifecycle.py +0 -0
- {pytest_asyncio_concurrent-0.2.0 → pytest_asyncio_concurrent-0.2.2}/tests/test_fixture_scoping.py +0 -0
- {pytest_asyncio_concurrent-0.2.0 → pytest_asyncio_concurrent-0.2.2}/tests/test_grouping.py +0 -0
- {pytest_asyncio_concurrent-0.2.0 → pytest_asyncio_concurrent-0.2.2}/tests/test_status.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: pytest-asyncio-concurrent
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Pytest plugin to execute python async tests concurrently.
|
|
5
5
|
Author-email: Zane Chen <czl970721@gmail.com>
|
|
6
6
|
Maintainer-email: Zane Chen <czl970721@gmail.com>
|
|
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
|
|
|
7
7
|
[project]
|
|
8
8
|
name = "pytest-asyncio-concurrent"
|
|
9
9
|
description = "Pytest plugin to execute python async tests concurrently."
|
|
10
|
-
version = "0.2.
|
|
10
|
+
version = "0.2.2"
|
|
11
11
|
readme = "README.rst"
|
|
12
12
|
requires-python = ">=3.8"
|
|
13
13
|
authors = [
|
|
@@ -84,7 +84,7 @@ concurrency = [
|
|
|
84
84
|
show_missing = true
|
|
85
85
|
|
|
86
86
|
[tool.bumpversion]
|
|
87
|
-
current_version = "0.2.
|
|
87
|
+
current_version = "0.2.2"
|
|
88
88
|
parse = """(?x)
|
|
89
89
|
(?P<major>0|[1-9]\\d*)\\.
|
|
90
90
|
(?P<minor>0|[1-9]\\d*)\\.
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
import functools
|
|
2
3
|
import inspect
|
|
3
4
|
import uuid
|
|
4
5
|
import warnings
|
|
5
6
|
import sys
|
|
7
|
+
import contextlib
|
|
6
8
|
|
|
7
9
|
from typing import (
|
|
8
10
|
Any,
|
|
@@ -15,12 +17,13 @@ from typing import (
|
|
|
15
17
|
Dict,
|
|
16
18
|
Sequence,
|
|
17
19
|
Union,
|
|
20
|
+
ContextManager,
|
|
18
21
|
)
|
|
19
22
|
|
|
23
|
+
import pluggy
|
|
20
24
|
import pytest
|
|
21
25
|
from _pytest import timing
|
|
22
26
|
from _pytest import outcomes
|
|
23
|
-
from _pytest import warnings as pytest_warnings
|
|
24
27
|
|
|
25
28
|
from .grouping import (
|
|
26
29
|
AsyncioConcurrentGroup,
|
|
@@ -187,37 +190,27 @@ def pytest_runtest_protocol_async_group(
|
|
|
187
190
|
)
|
|
188
191
|
)
|
|
189
192
|
|
|
190
|
-
|
|
193
|
+
item_passed_setup: List[AsyncioConcurrentGroupMember] = []
|
|
194
|
+
coros: List[Coroutine] = []
|
|
195
|
+
loop = asyncio.get_event_loop()
|
|
191
196
|
|
|
192
197
|
for childFunc in group.children:
|
|
193
198
|
childFunc.ihook.pytest_runtest_logstart(
|
|
194
199
|
nodeid=childFunc.nodeid, location=childFunc.location
|
|
195
200
|
)
|
|
196
201
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
report = _call_and_report(
|
|
201
|
-
_setup_child(childFunc, with_group=(not group.has_setup)), childFunc, "setup"
|
|
202
|
-
)
|
|
202
|
+
report = _call_and_report(_setup_child(childFunc), childFunc, "setup")
|
|
203
|
+
if report.passed:
|
|
204
|
+
item_passed_setup.append(childFunc)
|
|
203
205
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
continue
|
|
206
|
+
for childFunc in item_passed_setup:
|
|
207
|
+
coros.append(_call_and_report_runtest_async(childFunc))
|
|
207
208
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
for i, childFunc in enumerate(group.children):
|
|
211
|
-
# teardown group with the last test.
|
|
212
|
-
_call_and_report(
|
|
213
|
-
_teardown_child(
|
|
214
|
-
childFunc, nextgroup=nextgroup, with_group=(i == len(group.children) - 1)
|
|
215
|
-
),
|
|
216
|
-
childFunc,
|
|
217
|
-
"teardown",
|
|
218
|
-
)
|
|
209
|
+
loop.run_until_complete(asyncio.gather(*coros))
|
|
219
210
|
|
|
220
211
|
for childFunc in group.children:
|
|
212
|
+
_call_and_report(_teardown_child(childFunc, nextgroup=nextgroup), childFunc, "teardown")
|
|
213
|
+
|
|
221
214
|
childFunc.ihook.pytest_runtest_logfinish(
|
|
222
215
|
nodeid=childFunc.nodeid, location=childFunc.location
|
|
223
216
|
)
|
|
@@ -225,29 +218,15 @@ def pytest_runtest_protocol_async_group(
|
|
|
225
218
|
return True
|
|
226
219
|
|
|
227
220
|
|
|
228
|
-
def
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
coros: List[Coroutine] = []
|
|
236
|
-
loop = asyncio.get_event_loop()
|
|
237
|
-
|
|
238
|
-
for childFunc in items:
|
|
239
|
-
coros.append(_async_callinfo_from_call(hook_invoker(childFunc)))
|
|
240
|
-
|
|
241
|
-
call_result = loop.run_until_complete(asyncio.gather(*coros))
|
|
242
|
-
|
|
243
|
-
for childFunc, call in zip(items, call_result):
|
|
244
|
-
report = childFunc.ihook.pytest_runtest_makereport(item=childFunc, call=call)
|
|
245
|
-
childFunc.ihook.pytest_runtest_logreport(report=report)
|
|
221
|
+
async def _call_and_report_runtest_async(item: AsyncioConcurrentGroupMember) -> None:
|
|
222
|
+
callinfo = await _async_callinfo_from_call(
|
|
223
|
+
functools.partial(item.ihook.pytest_runtest_call_async, item=item) # type: ignore
|
|
224
|
+
)
|
|
225
|
+
report = item.ihook.pytest_runtest_makereport(item=item, call=callinfo)
|
|
226
|
+
item.ihook.pytest_runtest_logreport(report=report)
|
|
246
227
|
|
|
247
228
|
|
|
248
|
-
def _setup_child(
|
|
249
|
-
item: AsyncioConcurrentGroupMember, with_group: bool = False
|
|
250
|
-
) -> Callable[[], None]:
|
|
229
|
+
def _setup_child(item: AsyncioConcurrentGroupMember) -> Callable[[], None]:
|
|
251
230
|
"""
|
|
252
231
|
Setup flow for normal pytest tests:
|
|
253
232
|
- Push all nodes onto `SetupState`, start from furthest.
|
|
@@ -263,7 +242,7 @@ def _setup_child(
|
|
|
263
242
|
"""
|
|
264
243
|
|
|
265
244
|
def inner() -> None:
|
|
266
|
-
if
|
|
245
|
+
if not item.group.has_setup:
|
|
267
246
|
item.ihook.pytest_runtest_setup_async_group(item=item.group)
|
|
268
247
|
|
|
269
248
|
item.config.pluginmanager.subset_hook_caller(
|
|
@@ -276,7 +255,6 @@ def _setup_child(
|
|
|
276
255
|
def _teardown_child(
|
|
277
256
|
item: AsyncioConcurrentGroupMember,
|
|
278
257
|
nextgroup: Optional[AsyncioConcurrentGroup],
|
|
279
|
-
with_group: bool = False,
|
|
280
258
|
) -> Callable[[], None]:
|
|
281
259
|
"""
|
|
282
260
|
Similar to setup.
|
|
@@ -300,7 +278,7 @@ def _teardown_child(
|
|
|
300
278
|
exceptions.append(e)
|
|
301
279
|
|
|
302
280
|
try:
|
|
303
|
-
if
|
|
281
|
+
if len(item.group.children_finalizer) == 0:
|
|
304
282
|
item.ihook.pytest_runtest_teardown_async_group(item=item.group, nextitem=nextgroup)
|
|
305
283
|
except Exception as e:
|
|
306
284
|
if isinstance(e, BaseExceptionGroup):
|
|
@@ -384,18 +362,54 @@ def pytest_runtest_teardown_handle_async_function(
|
|
|
384
362
|
item.group.teardown_child(item)
|
|
385
363
|
|
|
386
364
|
|
|
387
|
-
# =========================== #
|
|
365
|
+
# =========================== # Captures #===========================#
|
|
388
366
|
|
|
389
367
|
|
|
390
368
|
@pytest.hookimpl(specname="pytest_runtest_protocol_async_group", wrapper=True, tryfirst=True)
|
|
391
369
|
def pytest_runtest_protocol_async_group_warning(
|
|
392
370
|
group: "AsyncioConcurrentGroup", nextgroup: Optional["AsyncioConcurrentGroup"]
|
|
393
371
|
) -> Generator[None, object, object]:
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
372
|
+
with_pytest_runtest_protocol_warning = _with_specific_hook_wrapped(
|
|
373
|
+
group.ihook.pytest_runtest_protocol, "warnings"
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
if with_pytest_runtest_protocol_warning:
|
|
377
|
+
with with_pytest_runtest_protocol_warning(item=group, nextitem=nextgroup):
|
|
378
|
+
result = yield
|
|
379
|
+
|
|
380
|
+
return result
|
|
381
|
+
|
|
382
|
+
return (yield)
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
@pytest.hookimpl(specname="pytest_runtest_call_async", wrapper=True, tryfirst=True)
|
|
386
|
+
def pytest_runtest_call_async_logging(item: pytest.Item) -> Generator[None, object, object]:
|
|
387
|
+
with_pytest_runtest_call_logging = _with_specific_hook_wrapped(
|
|
388
|
+
item.ihook.pytest_runtest_call, "logging-plugin"
|
|
389
|
+
)
|
|
390
|
+
|
|
391
|
+
if with_pytest_runtest_call_logging:
|
|
392
|
+
with with_pytest_runtest_call_logging(item=item):
|
|
393
|
+
result = yield
|
|
394
|
+
|
|
395
|
+
return result
|
|
396
|
+
|
|
397
|
+
return (yield)
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
@pytest.hookimpl(specname="pytest_runtest_call_async", wrapper=True, tryfirst=True)
|
|
401
|
+
def pytest_runtest_call_async_capture(item: pytest.Item) -> Generator[None, object, object]:
|
|
402
|
+
with_pytest_runtest_call_capture = _with_specific_hook_wrapped(
|
|
403
|
+
item.ihook.pytest_runtest_call, "capturemanager"
|
|
404
|
+
)
|
|
405
|
+
|
|
406
|
+
if with_pytest_runtest_call_capture:
|
|
407
|
+
with with_pytest_runtest_call_capture(item=item):
|
|
408
|
+
result = yield
|
|
409
|
+
|
|
410
|
+
return result
|
|
411
|
+
|
|
412
|
+
return (yield)
|
|
399
413
|
|
|
400
414
|
|
|
401
415
|
# =========================== # helper #===========================#
|
|
@@ -465,3 +479,25 @@ def _call_and_report(
|
|
|
465
479
|
):
|
|
466
480
|
item.ihook.pytest_exception_interact(node=item, call=call, report=report)
|
|
467
481
|
return report
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
def _with_specific_hook_wrapped(
|
|
485
|
+
hook: pluggy.HookCaller,
|
|
486
|
+
plugin: str,
|
|
487
|
+
) -> Optional[Callable[..., ContextManager]]:
|
|
488
|
+
try:
|
|
489
|
+
hookimpl = next(h for h in hook.get_hookimpls() if h.plugin_name == plugin)
|
|
490
|
+
except StopIteration:
|
|
491
|
+
return None
|
|
492
|
+
|
|
493
|
+
@contextlib.contextmanager
|
|
494
|
+
def cm(**kwargs: Dict) -> Generator:
|
|
495
|
+
gen = hookimpl.function(**{k: v for k, v in kwargs.items() if k in hookimpl.argnames})
|
|
496
|
+
next(gen) # type: ignore
|
|
497
|
+
yield
|
|
498
|
+
try:
|
|
499
|
+
next(gen) # type: ignore
|
|
500
|
+
except StopIteration:
|
|
501
|
+
pass
|
|
502
|
+
|
|
503
|
+
return cm
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: pytest-asyncio-concurrent
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Pytest plugin to execute python async tests concurrently.
|
|
5
5
|
Author-email: Zane Chen <czl970721@gmail.com>
|
|
6
6
|
Maintainer-email: Zane Chen <czl970721@gmail.com>
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytest_asyncio_concurrent-0.2.0 → pytest_asyncio_concurrent-0.2.2}/tests/test_async_fixture.py
RENAMED
|
File without changes
|
{pytest_asyncio_concurrent-0.2.0 → pytest_asyncio_concurrent-0.2.2}/tests/test_compatibility.py
RENAMED
|
File without changes
|
|
File without changes
|
{pytest_asyncio_concurrent-0.2.0 → pytest_asyncio_concurrent-0.2.2}/tests/test_fixture_lifecycle.py
RENAMED
|
File without changes
|
{pytest_asyncio_concurrent-0.2.0 → pytest_asyncio_concurrent-0.2.2}/tests/test_fixture_scoping.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|