# Path: aiostream/aiter_utils.py
# class AsyncIteratorContext(AsyncIterator):
#     """Asynchronous iterator with context management.
# 
#     The context management makes sure the aclose asynchronous method
#     of the corresponding iterator has run before it exits. It also issues
#     warnings and RuntimeError if it is used incorrectly.
# 
#     Correct usage::
# 
#         ait = some_asynchronous_iterable()
#         async with AsyncIteratorContext(ait) as safe_ait:
#             async for item in safe_ait:
#                 <block>
# 
#     It is nonetheless not meant to use directly.
#     Prefer aitercontext helper instead.
#     """
# 
#     _STANDBY = "STANDBY"
#     _RUNNING = "RUNNING"
#     _FINISHED = "FINISHED"
# 
#     def __init__(self, aiterator):
#         """Initialize with an asynchrnous iterator."""
#         assert_async_iterator(aiterator)
#         if isinstance(aiterator, AsyncIteratorContext):
#             raise TypeError(f"{aiterator!r} is already an AsyncIteratorContext")
#         self._state = self._STANDBY
#         self._aiterator = aiterator
# 
#     def __aiter__(self):
#         return self
# 
#     def __anext__(self):
#         if self._state == self._FINISHED:
#             raise RuntimeError(
#                 f"{type(self).__name__} is closed and cannot be iterated"
#             )
#         if self._state == self._STANDBY:
#             warnings.warn(
#                 f"{type(self).__name__} is iterated outside of its context",
#                 stacklevel=2,
#             )
#         return anext(self._aiterator)
# 
#     async def __aenter__(self):
#         if self._state == self._RUNNING:
#             raise RuntimeError(f"{type(self).__name__} has already been entered")
#         if self._state == self._FINISHED:
#             raise RuntimeError(
#                 f"{type(self).__name__} is closed and cannot be iterated"
#             )
#         self._state = self._RUNNING
#         return self
# 
#     async def __aexit__(self, typ, value, traceback):
#         try:
#             if self._state == self._FINISHED:
#                 return False
#             try:
# 
#                 # No exception to throw
#                 if typ is None:
#                     return False
# 
#                 # Prevent GeneratorExit from being silenced
#                 if typ is GeneratorExit:
#                     return False
# 
#                 # No method to throw
#                 if not hasattr(self._aiterator, "athrow"):
#                     return False
# 
#                 # No frame to throw
#                 if not getattr(self._aiterator, "ag_frame", True):
#                     return False
# 
#                 # Cannot throw at the moment
#                 if getattr(self._aiterator, "ag_running", False):
#                     return False
# 
#                 # Throw
#                 try:
#                     await self._aiterator.athrow(typ, value, traceback)
#                     raise RuntimeError("Async iterator didn't stop after athrow()")
# 
#                 # Exception has been (most probably) silenced
#                 except StopAsyncIteration as exc:
#                     return exc is not value
# 
#                 # A (possibly new) exception has been raised
#                 except BaseException as exc:
#                     if exc is value:
#                         return False
#                     raise
#             finally:
#                 # Look for an aclose method
#                 aclose = getattr(self._aiterator, "aclose", None)
# 
#                 # The ag_running attribute has been introduced with python 3.8
#                 running = getattr(self._aiterator, "ag_running", False)
#                 closed = not getattr(self._aiterator, "ag_frame", True)
# 
#                 # A RuntimeError is raised if aiterator is running or closed
#                 if aclose and not running and not closed:
#                     try:
#                         await aclose()
# 
#                     # Work around bpo-35409
#                     except GeneratorExit:
#                         pass  # pragma: no cover
#         finally:
#             self._state = self._FINISHED
# 
#     async def aclose(self):
#         await self.__aexit__(None, None, None)
# 
#     async def athrow(self, exc):
#         if self._state == self._FINISHED:
#             raise RuntimeError(f"{type(self).__name__} is closed and cannot be used")
#         return await self._aiterator.athrow(exc)
# 
# Path: aiostream/aiter_utils.py
# def aitercontext(aiterable, *, cls=AsyncIteratorContext):
#     """Return an asynchronous context manager from an asynchronous iterable.
# 
#     The context management makes sure the aclose asynchronous method
#     has run before it exits. It also issues warnings and RuntimeError
#     if it is used incorrectly.
# 
#     It is safe to use with any asynchronous iterable and prevent
#     asynchronous iterator context to be wrapped twice.
# 
#     Correct usage::
# 
#         ait = some_asynchronous_iterable()
#         async with aitercontext(ait) as safe_ait:
#             async for item in safe_ait:
#                 <block>
# 
#     An optional subclass of AsyncIteratorContext can be provided.
#     This class will be used to wrap the given iterable.
#     """
#     assert issubclass(cls, AsyncIteratorContext)
#     aiterator = aiter(aiterable)
#     if isinstance(aiterator, cls):
#         return aiterator
#     return cls(aiterator)
# 
# def assert_async_iterable(obj):
#     """Raise a TypeError if the given object is not an
#     asynchronous iterable.
#     """
#     if not is_async_iterable(obj):
#         raise TypeError(f"{type(obj).__name__!r} object is not async iterable")


import inspect
import functools
from collections.abc import AsyncIterable, Awaitable
from .aiter_utils import AsyncIteratorContext
from .aiter_utils import aitercontext, assert_async_iterable
        from .stream import chain
        from .stream import getitem
    # Disable sync iteration
    # This is necessary because __getitem__ is defined
    # which is a valid fallback for for-loops in python
    __iter__ = None

    def stream(self):
        """Return a streamer context for safe iteration.

        Example::

            xs = stream.count()
            async with xs.stream() as streamer:
                async for item in streamer:
                    <block>

        """
        return self.__aiter__()

    # Advertise the proper synthax for entering a stream context

    __aexit__ = None

    async def __aenter__(self):
        raise TypeError(
            "A stream object cannot be used as a context manager. "
            "Use the `stream` method instead: "
            "`async with xs.stream() as streamer`"
        )



# Path: aiostream/aiter_utils.py
# class AsyncIteratorContext(AsyncIterator):
#     """Asynchronous iterator with context management.
# 
#     The context management makes sure the aclose asynchronous method
#     of the corresponding iterator has run before it exits. It also issues
#     warnings and RuntimeError if it is used incorrectly.
# 
#     Correct usage::
# 
#         ait = some_asynchronous_iterable()
#         async with AsyncIteratorContext(ait) as safe_ait:
#             async for item in safe_ait:
#                 <block>
# 
#     It is nonetheless not meant to use directly.
#     Prefer aitercontext helper instead.
#     """
# 
#     _STANDBY = "STANDBY"
#     _RUNNING = "RUNNING"
#     _FINISHED = "FINISHED"
# 
#     def __init__(self, aiterator):
#         """Initialize with an asynchrnous iterator."""
#         assert_async_iterator(aiterator)
#         if isinstance(aiterator, AsyncIteratorContext):
#             raise TypeError(f"{aiterator!r} is already an AsyncIteratorContext")
#         self._state = self._STANDBY
#         self._aiterator = aiterator
# 
#     def __aiter__(self):
#         return self
# 
#     def __anext__(self):
#         if self._state == self._FINISHED:
#             raise RuntimeError(
#                 f"{type(self).__name__} is closed and cannot be iterated"
#             )
#         if self._state == self._STANDBY:
#             warnings.warn(
#                 f"{type(self).__name__} is iterated outside of its context",
#                 stacklevel=2,
#             )
#         return anext(self._aiterator)
# 
#     async def __aenter__(self):
#         if self._state == self._RUNNING:
#             raise RuntimeError(f"{type(self).__name__} has already been entered")
#         if self._state == self._FINISHED:
#             raise RuntimeError(
#                 f"{type(self).__name__} is closed and cannot be iterated"
#             )
#         self._state = self._RUNNING
#         return self
# 
#     async def __aexit__(self, typ, value, traceback):
#         try:
#             if self._state == self._FINISHED:
#                 return False
#             try:
# 
#                 # No exception to throw
#                 if typ is None:
#                     return False
# 
#                 # Prevent GeneratorExit from being silenced
#                 if typ is GeneratorExit:
#                     return False
# 
#                 # No method to throw
#                 if not hasattr(self._aiterator, "athrow"):
#                     return False
# 
#                 # No frame to throw
#                 if not getattr(self._aiterator, "ag_frame", True):
#                     return False
# 
#                 # Cannot throw at the moment
#                 if getattr(self._aiterator, "ag_running", False):
#                     return False
# 
#                 # Throw
#                 try:
#                     await self._aiterator.athrow(typ, value, traceback)
#                     raise RuntimeError("Async iterator didn't stop after athrow()")
# 
#                 # Exception has been (most probably) silenced
#                 except StopAsyncIteration as exc:
#                     return exc is not value
# 
#                 # A (possibly new) exception has been raised
#                 except BaseException as exc:
#                     if exc is value:
#                         return False
#                     raise
#             finally:
#                 # Look for an aclose method
#                 aclose = getattr(self._aiterator, "aclose", None)
# 
#                 # The ag_running attribute has been introduced with python 3.8
#                 running = getattr(self._aiterator, "ag_running", False)
#                 closed = not getattr(self._aiterator, "ag_frame", True)
# 
#                 # A RuntimeError is raised if aiterator is running or closed
#                 if aclose and not running and not closed:
#                     try:
#                         await aclose()
# 
#                     # Work around bpo-35409
#                     except GeneratorExit:
#                         pass  # pragma: no cover
#         finally:
#             self._state = self._FINISHED
# 
#     async def aclose(self):
#         await self.__aexit__(None, None, None)
# 
#     async def athrow(self, exc):
#         if self._state == self._FINISHED:
#             raise RuntimeError(f"{type(self).__name__} is closed and cannot be used")
#         return await self._aiterator.athrow(exc)
# 
# Path: aiostream/aiter_utils.py
# def aitercontext(aiterable, *, cls=AsyncIteratorContext):
#     """Return an asynchronous context manager from an asynchronous iterable.
# 
#     The context management makes sure the aclose asynchronous method
#     has run before it exits. It also issues warnings and RuntimeError
#     if it is used incorrectly.
# 
#     It is safe to use with any asynchronous iterable and prevent
#     asynchronous iterator context to be wrapped twice.
# 
#     Correct usage::
# 
#         ait = some_asynchronous_iterable()
#         async with aitercontext(ait) as safe_ait:
#             async for item in safe_ait:
#                 <block>
# 
#     An optional subclass of AsyncIteratorContext can be provided.
#     This class will be used to wrap the given iterable.
#     """
#     assert issubclass(cls, AsyncIteratorContext)
#     aiterator = aiter(aiterable)
#     if isinstance(aiterator, cls):
#         return aiterator
#     return cls(aiterator)
# 
# def assert_async_iterable(obj):
#     """Raise a TypeError if the given object is not an
#     asynchronous iterable.
#     """
#     if not is_async_iterable(obj):
#         raise TypeError(f"{type(obj).__name__!r} object is not async iterable")


# Path: aiostream/core.py
import inspect
import functools
from collections.abc import AsyncIterable, Awaitable
from .aiter_utils import AsyncIteratorContext
from .aiter_utils import aitercontext, assert_async_iterable
        from .stream import chain
        from .stream import getitem

    # Disable sync iteration
    # This is necessary because __getitem__ is defined
    # which is a valid fallback for for-loops in python
    __iter__ = None

    def stream(self):
        """Return a streamer context for safe iteration.

        Example::

            xs = stream.count()
            async with xs.stream() as streamer:
                async for item in streamer:
                    <block>

        """
        return self.__aiter__()

    # Advertise the proper synthax for entering a stream context

    __aexit__ = None

    async def __aenter__(self):
        raise TypeError(
            "A stream object cannot be used as a context manager. "
            "Use the `stream` method instead: "
            "`async with xs.stream() as streamer`"
        )



class Streamer(AsyncIteratorContext, Stream):