matrx-utils 2.0.0__tar.gz → 2.0.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.
Files changed (122) hide show
  1. matrx_utils-2.0.2/AGENTS.md +1 -0
  2. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/PKG-INFO +1 -1
  3. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/__init__.py +2 -0
  4. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/diagnostics/loop_watchdog.py +10 -0
  5. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/utils/__init__.py +3 -1
  6. matrx_utils-2.0.2/matrx_utils/utils/singleflight.py +46 -0
  7. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/pyproject.toml +1 -1
  8. matrx_utils-2.0.2/tests/test_loop_watchdog_signature.py +16 -0
  9. matrx_utils-2.0.2/tests/test_singleflight.py +79 -0
  10. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/.gitignore +0 -0
  11. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/CLAUDE.md +0 -0
  12. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/README.md +0 -0
  13. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/MODULE_README.md +0 -0
  14. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/RENDEZVOUS_FEATURE.md +0 -0
  15. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/backoff.py +0 -0
  16. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/MODULE_README.md +0 -0
  17. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/__init__.py +0 -0
  18. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/code_context.py +0 -0
  19. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/config.yaml +0 -0
  20. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/docs/AST_UPGRADE_TASK.md +0 -0
  21. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/docs/LANGUAGE_COVERAGE.md +0 -0
  22. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/docs/MODULE_README_SPEC.md +0 -0
  23. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/docs/MULTI_MODULE_TASK.md +0 -0
  24. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/docs/README.md +0 -0
  25. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/docs/ROADMAP.md +0 -0
  26. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/generate_module_readme.py +0 -0
  27. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/tests/MODULE_README.md +0 -0
  28. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/tests/__init__.py +0 -0
  29. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/tests/test_code_extractor.py +0 -0
  30. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/tests/test_file_discovery.py +0 -0
  31. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/tests/test_integration.py +0 -0
  32. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/tests/test_output_modes.py +0 -0
  33. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/tests/test_tree_generator.py +0 -0
  34. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/conf.py +0 -0
  35. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/ctx.py +0 -0
  36. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/data_handling/MODULE_README.md +0 -0
  37. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/data_handling/__init__.py +0 -0
  38. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/data_handling/data_transformer.py +0 -0
  39. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/data_handling/errors.py +0 -0
  40. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/data_handling/utils.py +0 -0
  41. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/data_handling/validators.py +0 -0
  42. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/data_in_code/current_data.py +0 -0
  43. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/data_in_code/current_ts_data.ts +0 -0
  44. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/data_in_code/make_updates.py +0 -0
  45. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/data_uri.py +0 -0
  46. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/diagnostics/__init__.py +0 -0
  47. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/diagnostics/inflight.py +0 -0
  48. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/fancy_prints/MODULE_README.md +0 -0
  49. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/fancy_prints/__init__.py +0 -0
  50. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/fancy_prints/colors.py +0 -0
  51. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/fancy_prints/fancy_prints.py +0 -0
  52. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/fancy_prints/matrx_json_converter.py +0 -0
  53. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/fancy_prints/matrx_print_logger.py +0 -0
  54. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/fancy_prints/redaction.py +0 -0
  55. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/fancy_prints/truncation.py +0 -0
  56. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/field_processing/__init__.py +0 -0
  57. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/field_processing/dataclass_generator.py +0 -0
  58. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/field_processing/field_handler.py +0 -0
  59. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/hashing.py +0 -0
  60. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/http_client.py +0 -0
  61. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/ids.py +0 -0
  62. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/local_dev_utils/analyze-jsonl.py +0 -0
  63. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/local_dev_utils/copy_project.py +0 -0
  64. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/local_dev_utils/create_directories.py +0 -0
  65. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/local_dev_utils/extract_code.py +0 -0
  66. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/local_dev_utils/find_unused.py +0 -0
  67. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/local_dev_utils/generate_readme.py +0 -0
  68. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/local_dev_utils/import_checker.py +0 -0
  69. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/local_dev_utils/link_generator.py +0 -0
  70. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/local_dev_utils/local_mcp_tester.py +0 -0
  71. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/local_dev_utils/next_test_dir_config.py +0 -0
  72. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/local_dev_utils/package_inspector.py +0 -0
  73. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/local_dev_utils/package_size_analyzer.py +0 -0
  74. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/local_dev_utils/package_usage_scanner.py +0 -0
  75. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/local_dev_utils/react_links_direct.py +0 -0
  76. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/package_analysis/__init__.py +0 -0
  77. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/package_analysis/packages.py +0 -0
  78. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/package_analysis/reports.py +0 -0
  79. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/package_analysis/scan_excludes.py +0 -0
  80. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/profiler/__init__.py +0 -0
  81. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/profiler/profile_utility.py +0 -0
  82. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/quality_engine.py +0 -0
  83. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/react_analysis/MODULE_README.md +0 -0
  84. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/react_analysis/__init__.py +0 -0
  85. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/react_analysis/analyze_react_imports.py +0 -0
  86. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/react_analysis/collision_summary.py +0 -0
  87. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/react_analysis/extract_all_exports.py +0 -0
  88. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/react_analysis/extract_exports.py +0 -0
  89. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/react_analysis/find_invalid_imports.py +0 -0
  90. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/react_analysis/generate_full_index_with_files.py +0 -0
  91. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/react_analysis/generate_full_index_with_structure.py +0 -0
  92. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/react_analysis/generate_react_index.py +0 -0
  93. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/react_analysis/get_and_analyze.py +0 -0
  94. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/react_analysis/name_collision_analyer.py +0 -0
  95. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/react_analysis/utils.py +0 -0
  96. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/react_analysis/z_configs.py +0 -0
  97. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/rendezvous.py +0 -0
  98. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/runtime_env.py +0 -0
  99. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/secure_random.py +0 -0
  100. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/suggest.py +0 -0
  101. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/timeutils.py +0 -0
  102. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/utils/clear_terminal.py +0 -0
  103. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/utils/detached_task.py +0 -0
  104. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/utils/get_dir_structure.py +0 -0
  105. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/utils/testing.py +0 -0
  106. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/scripts/release.sh +0 -0
  107. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/tests/MODULE_README.md +0 -0
  108. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/tests/conftest.py +0 -0
  109. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/tests/field_generation.py +0 -0
  110. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/tests/field_processing.py +0 -0
  111. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/tests/get_dir_structure_test.py +0 -0
  112. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/tests/load_env_for_test.py +0 -0
  113. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/tests/print_link_test.py +0 -0
  114. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/tests/test_backoff.py +0 -0
  115. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/tests/test_data_uri.py +0 -0
  116. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/tests/test_detached_task.py +0 -0
  117. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/tests/test_http_client.py +0 -0
  118. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/tests/test_quality_engine.py +0 -0
  119. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/tests/test_rendezvous.py +0 -0
  120. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/tests/test_runtime_env.py +0 -0
  121. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/tests/test_secure_random.py +0 -0
  122. {matrx_utils-2.0.0 → matrx_utils-2.0.2}/tests/test_suggest.py +0 -0
@@ -0,0 +1 @@
1
+ CLAUDE.md
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: matrx-utils
3
- Version: 2.0.0
3
+ Version: 2.0.2
4
4
  Summary: Core shared utilities for the Matrx ecosystem (file handling now lives in matrx-files)
5
5
  Project-URL: Homepage, https://github.com/AI-Matrix-Engine/aidream-current
6
6
  Project-URL: Repository, https://github.com/AI-Matrix-Engine/aidream-current
@@ -51,6 +51,7 @@ from .fancy_prints import (
51
51
  vcprint,
52
52
  )
53
53
  from .utils import (
54
+ AsyncSingleFlight,
54
55
  async_test_wrapper,
55
56
  cleanup_async_resources,
56
57
  clear_terminal,
@@ -297,6 +298,7 @@ from .utils import (
297
298
  )
298
299
 
299
300
  __all__ = [
301
+ "AsyncSingleFlight",
300
302
  # rendezvous
301
303
  "Rendezvous",
302
304
  "RendezvousStats",
@@ -65,6 +65,16 @@ def _stall_signature(name: str, stack_text: str | None) -> str:
65
65
  if not stack_text:
66
66
  return f"{name}:no-stack"
67
67
  sites = [line.strip() for line in stack_text.split("\n") if line.lstrip().startswith("File ")]
68
+ relevant_sites = [
69
+ site
70
+ for site in sites
71
+ if "/site-packages/" not in site and "/lib/python" not in site
72
+ ]
73
+ # Transport implementation frames (SSL read/write/handshake) vary within
74
+ # one outage and previously defeated dedupe. Prefer application/package
75
+ # call sites while retaining the full stack in the report payload.
76
+ if relevant_sites:
77
+ sites = relevant_sites
68
78
  digest = hashlib.sha1(("\n".join(sites)).encode("utf-8")).hexdigest()[:16]
69
79
  return f"{name}:{digest}"
70
80
 
@@ -2,6 +2,7 @@ from .get_dir_structure import generate_directory_structure, generate_and_save_d
2
2
  from .clear_terminal import clear_terminal
3
3
  from .testing import cleanup_async_resources, async_test_wrapper
4
4
  from .detached_task import detached_task
5
+ from .singleflight import AsyncSingleFlight
5
6
 
6
7
 
7
8
  __all__ = [
@@ -11,4 +12,5 @@ __all__ = [
11
12
  "cleanup_async_resources",
12
13
  "async_test_wrapper",
13
14
  "detached_task",
14
- ]
15
+ "AsyncSingleFlight",
16
+ ]
@@ -0,0 +1,46 @@
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+ from collections.abc import Awaitable, Callable, Hashable
5
+ from typing import Generic, TypeVar
6
+
7
+
8
+ K = TypeVar("K", bound=Hashable)
9
+ V = TypeVar("V")
10
+
11
+
12
+ class AsyncSingleFlight(Generic[K, V]):
13
+ """Collapse concurrent work for the same key into one cancellation-safe task."""
14
+
15
+ def __init__(self) -> None:
16
+ self._tasks: dict[K, asyncio.Task[V]] = {}
17
+
18
+ @property
19
+ def pending(self) -> int:
20
+ return len(self._tasks)
21
+
22
+ async def do(self, key: K, factory: Callable[[], Awaitable[V]]) -> V:
23
+ task = self._tasks.get(key)
24
+ if task is None or task.done():
25
+ # Keys can be credentials or user identifiers. Never expose them in
26
+ # task names, trace dumps, or process introspection.
27
+ async def invoke() -> V:
28
+ return await factory()
29
+
30
+ task = asyncio.create_task(invoke(), name="singleflight")
31
+ self._tasks[key] = task
32
+ task.add_done_callback(lambda done, flight_key=key: self._finish(flight_key, done))
33
+
34
+ # A caller disconnect/cancellation must not cancel work shared by other
35
+ # callers. The task owns its own lifetime and is removed on completion.
36
+ return await asyncio.shield(task)
37
+
38
+ def _finish(self, key: K, task: asyncio.Task[V]) -> None:
39
+ if self._tasks.get(key) is task:
40
+ self._tasks.pop(key, None)
41
+ # Retrieve unexpected exceptions even when every waiter was cancelled,
42
+ # preventing "Task exception was never retrieved" during shutdown.
43
+ try:
44
+ task.exception()
45
+ except asyncio.CancelledError:
46
+ pass
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "matrx-utils"
3
- version = "2.0.0"
3
+ version = "2.0.2"
4
4
  description = "Core shared utilities for the Matrx ecosystem (file handling now lives in matrx-files)"
5
5
  readme = "README.md"
6
6
  license = { text = "MIT" }
@@ -0,0 +1,16 @@
1
+ from matrx_utils.diagnostics.loop_watchdog import _stall_signature
2
+
3
+
4
+ def test_transport_frames_do_not_fragment_stall_signature() -> None:
5
+ shared = ' File "/srv/aidream/aidream/api/app.py", line 500, in run\n'
6
+ ssl_read = (
7
+ shared
8
+ + ' File "/usr/lib/python3.13/asyncio/sslproto.py", line 700, in read\n'
9
+ + ' File "/venv/site-packages/asyncpg/pool.py", line 100, in acquire\n'
10
+ )
11
+ ssl_write = (
12
+ shared
13
+ + ' File "/usr/lib/python3.13/asyncio/sslproto.py", line 800, in write\n'
14
+ + ' File "/venv/site-packages/asyncpg/pool.py", line 200, in connect\n'
15
+ )
16
+ assert _stall_signature("api", ssl_read) == _stall_signature("api", ssl_write)
@@ -0,0 +1,79 @@
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+
5
+ import pytest
6
+
7
+ from matrx_utils import AsyncSingleFlight
8
+
9
+
10
+ @pytest.mark.asyncio
11
+ async def test_same_key_runs_factory_once() -> None:
12
+ flight: AsyncSingleFlight[str, int] = AsyncSingleFlight()
13
+ started = asyncio.Event()
14
+ release = asyncio.Event()
15
+ calls = 0
16
+
17
+ async def work() -> int:
18
+ nonlocal calls
19
+ calls += 1
20
+ started.set()
21
+ await release.wait()
22
+ return 42
23
+
24
+ waiters = [asyncio.create_task(flight.do("key", work)) for _ in range(20)]
25
+ await started.wait()
26
+ assert calls == 1
27
+ assert flight.pending == 1
28
+
29
+ release.set()
30
+ assert await asyncio.gather(*waiters) == [42] * 20
31
+ assert flight.pending == 0
32
+
33
+
34
+ @pytest.mark.asyncio
35
+ async def test_cancelled_waiter_does_not_cancel_shared_work() -> None:
36
+ flight: AsyncSingleFlight[str, str] = AsyncSingleFlight()
37
+ started = asyncio.Event()
38
+ release = asyncio.Event()
39
+
40
+ async def work() -> str:
41
+ started.set()
42
+ await release.wait()
43
+ return "done"
44
+
45
+ first = asyncio.create_task(flight.do("key", work))
46
+ await started.wait()
47
+ second = asyncio.create_task(flight.do("key", work))
48
+ first.cancel()
49
+ with pytest.raises(asyncio.CancelledError):
50
+ await first
51
+
52
+ release.set()
53
+ assert await second == "done"
54
+ assert flight.pending == 0
55
+
56
+
57
+ @pytest.mark.asyncio
58
+ async def test_different_keys_run_independently() -> None:
59
+ flight: AsyncSingleFlight[str, str] = AsyncSingleFlight()
60
+ calls: list[str] = []
61
+
62
+ async def work(key: str) -> str:
63
+ calls.append(key)
64
+ await asyncio.sleep(0)
65
+ return key
66
+
67
+ assert await asyncio.gather(
68
+ flight.do("a", lambda: work("a")),
69
+ flight.do("b", lambda: work("b")),
70
+ ) == ["a", "b"]
71
+ assert sorted(calls) == ["a", "b"]
72
+
73
+
74
+ @pytest.mark.asyncio
75
+ async def test_factory_may_return_any_awaitable() -> None:
76
+ flight: AsyncSingleFlight[str, int] = AsyncSingleFlight()
77
+ future = asyncio.get_running_loop().create_future()
78
+ future.set_result(7)
79
+ assert await flight.do("future", lambda: future) == 7
File without changes
File without changes
File without changes