| """Async iterator lifecycle helper contracts.""" |
|
|
| import asyncio |
|
|
| import pytest |
|
|
| from free_claude_code.core.async_iterators import ( |
| AsyncCloseable, |
| try_close_async_iterator, |
| ) |
|
|
|
|
| class _Closeable: |
| def __init__(self, error: BaseException | None = None) -> None: |
| self._error = error |
| self.close_calls = 0 |
|
|
| async def aclose(self) -> None: |
| self.close_calls += 1 |
| if self._error is not None: |
| raise self._error |
|
|
|
|
| @pytest.mark.asyncio |
| async def test_try_close_async_iterator_closes_supported_value_once() -> None: |
| value = _Closeable() |
|
|
| assert isinstance(value, AsyncCloseable) |
| assert await try_close_async_iterator(value) is None |
| assert value.close_calls == 1 |
|
|
|
|
| @pytest.mark.asyncio |
| async def test_try_close_async_iterator_ignores_non_closeable_value() -> None: |
| assert await try_close_async_iterator(object()) is None |
|
|
|
|
| @pytest.mark.asyncio |
| async def test_try_close_async_iterator_returns_ordinary_close_failure() -> None: |
| failure = RuntimeError("close failed") |
| value = _Closeable(failure) |
|
|
| assert await try_close_async_iterator(value) is failure |
| assert value.close_calls == 1 |
|
|
|
|
| @pytest.mark.asyncio |
| async def test_try_close_async_iterator_propagates_cancellation() -> None: |
| value = _Closeable(asyncio.CancelledError()) |
|
|
| with pytest.raises(asyncio.CancelledError): |
| await try_close_async_iterator(value) |
|
|
| assert value.close_calls == 1 |
|
|