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.
- matrx_utils-2.0.2/AGENTS.md +1 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/PKG-INFO +1 -1
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/__init__.py +2 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/diagnostics/loop_watchdog.py +10 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/utils/__init__.py +3 -1
- matrx_utils-2.0.2/matrx_utils/utils/singleflight.py +46 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/pyproject.toml +1 -1
- matrx_utils-2.0.2/tests/test_loop_watchdog_signature.py +16 -0
- matrx_utils-2.0.2/tests/test_singleflight.py +79 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/.gitignore +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/CLAUDE.md +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/README.md +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/MODULE_README.md +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/RENDEZVOUS_FEATURE.md +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/backoff.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/MODULE_README.md +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/__init__.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/code_context.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/config.yaml +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/docs/AST_UPGRADE_TASK.md +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/docs/LANGUAGE_COVERAGE.md +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/docs/MODULE_README_SPEC.md +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/docs/MULTI_MODULE_TASK.md +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/docs/README.md +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/docs/ROADMAP.md +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/generate_module_readme.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/tests/MODULE_README.md +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/tests/__init__.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/tests/test_code_extractor.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/tests/test_file_discovery.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/tests/test_integration.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/tests/test_output_modes.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/tests/test_tree_generator.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/conf.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/ctx.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/data_handling/MODULE_README.md +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/data_handling/__init__.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/data_handling/data_transformer.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/data_handling/errors.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/data_handling/utils.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/data_handling/validators.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/data_in_code/current_data.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/data_in_code/current_ts_data.ts +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/data_in_code/make_updates.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/data_uri.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/diagnostics/__init__.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/diagnostics/inflight.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/fancy_prints/MODULE_README.md +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/fancy_prints/__init__.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/fancy_prints/colors.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/fancy_prints/fancy_prints.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/fancy_prints/matrx_json_converter.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/fancy_prints/matrx_print_logger.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/fancy_prints/redaction.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/fancy_prints/truncation.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/field_processing/__init__.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/field_processing/dataclass_generator.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/field_processing/field_handler.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/hashing.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/http_client.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/ids.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/local_dev_utils/analyze-jsonl.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/local_dev_utils/copy_project.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/local_dev_utils/create_directories.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/local_dev_utils/extract_code.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/local_dev_utils/find_unused.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/local_dev_utils/generate_readme.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/local_dev_utils/import_checker.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/local_dev_utils/link_generator.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/local_dev_utils/local_mcp_tester.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/local_dev_utils/next_test_dir_config.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/local_dev_utils/package_inspector.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/local_dev_utils/package_size_analyzer.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/local_dev_utils/package_usage_scanner.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/local_dev_utils/react_links_direct.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/package_analysis/__init__.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/package_analysis/packages.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/package_analysis/reports.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/package_analysis/scan_excludes.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/profiler/__init__.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/profiler/profile_utility.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/quality_engine.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/react_analysis/MODULE_README.md +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/react_analysis/__init__.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/react_analysis/analyze_react_imports.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/react_analysis/collision_summary.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/react_analysis/extract_all_exports.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/react_analysis/extract_exports.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/react_analysis/find_invalid_imports.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/react_analysis/generate_full_index_with_files.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/react_analysis/generate_full_index_with_structure.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/react_analysis/generate_react_index.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/react_analysis/get_and_analyze.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/react_analysis/name_collision_analyer.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/react_analysis/utils.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/react_analysis/z_configs.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/rendezvous.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/runtime_env.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/secure_random.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/suggest.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/timeutils.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/utils/clear_terminal.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/utils/detached_task.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/utils/get_dir_structure.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/utils/testing.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/scripts/release.sh +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/tests/MODULE_README.md +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/tests/conftest.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/tests/field_generation.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/tests/field_processing.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/tests/get_dir_structure_test.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/tests/load_env_for_test.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/tests/print_link_test.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/tests/test_backoff.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/tests/test_data_uri.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/tests/test_detached_task.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/tests/test_http_client.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/tests/test_quality_engine.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/tests/test_rendezvous.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/tests/test_runtime_env.py +0 -0
- {matrx_utils-2.0.0 → matrx_utils-2.0.2}/tests/test_secure_random.py +0 -0
- {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.
|
|
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
|
|
@@ -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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/tests/test_code_extractor.py
RENAMED
|
File without changes
|
{matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/tests/test_file_discovery.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/code_context/tests/test_tree_generator.py
RENAMED
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/local_dev_utils/package_size_analyzer.py
RENAMED
|
File without changes
|
{matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/local_dev_utils/package_usage_scanner.py
RENAMED
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/react_analysis/generate_full_index_with_files.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{matrx_utils-2.0.0 → matrx_utils-2.0.2}/matrx_utils/react_analysis/name_collision_analyer.py
RENAMED
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|