===== src/simpy/core.py =====
"""
Core components for event-discrete simulation environments.

"""
from __future__ import annotations
from heapq import heappop, heappush
from itertools import count
from types import MethodType
from typing import TYPE_CHECKING, Any, Generic, Iterable, List, Optional, Tuple, Type, TypeVar, Union
from simpy.events import NORMAL, URGENT, AllOf, AnyOf, Event, EventPriority, Process, ProcessGenerator, Timeout
Infinity: float = float('inf')
T = TypeVar('T')

class BoundClass(Generic[T]):
    """Allows classes to behave like methods.

    The ``__get__()`` descriptor is basically identical to
    ``function.__get__()`` and binds the first argument of the ``cls`` to the
    descriptor instance.

    """

    def __init__(self, cls: Type[T]):
        self.cls = cls

    def __get__(self, instance: Optional[BoundClass], owner: Optional[Type[BoundClass]]=None) -> Union[Type[T], MethodType]:
        if instance is None:
            return self.cls
        return MethodType(self.cls, instance)

    @staticmethod
    def bind_early(instance: object) -> None:
        """Bind all :class:`BoundClass` attributes of the *instance's* class
        to the instance itself to increase performance."""
        pass

class EmptySchedule(Exception):
    """Thrown by an :class:`Environment` if there are no further events to be
    processed."""

class StopSimulation(Exception):
    """Indicates that the simulation should stop now."""

    @classmethod
    def callback(cls, event: Event) -> None:
        """Used as callback in :meth:`Environment.run()` to stop the simulation
        when the *until* event occurred."""
        pass
SimTime = Union[int, float]

class Environment:
    """Execution environment for an event-based simulation. The passing of time
    is simulated by stepping from event to event.

    You can provide an *initial_time* for the environment. By default, it
    starts at ``0``.

    This class also provides aliases for common event types, for example
    :attr:`process`, :attr:`timeout` and :attr:`event`.

    """

    def __init__(self, initial_time: SimTime=0):
        self._now = initial_time
        self._queue: List[Tuple[SimTime, EventPriority, int, Event]] = []
        self._eid = count()
        self._active_proc: Optional[Process] = None
        BoundClass.bind_early(self)

    @property
    def now(self) -> SimTime:
        """The current simulation time."""
        pass

    @property
    def active_process(self) -> Optional[Process]:
        """The currently active process of the environment."""
        pass
    if TYPE_CHECKING:

        def process(self, generator: ProcessGenerator) -> Process:
            """Create a new :class:`~simpy.events.Process` instance for
            *generator*."""
            pass

        def timeout(self, delay: SimTime=0, value: Optional[Any]=None) -> Timeout:
            """Return a new :class:`~simpy.events.Timeout` event with a *delay*
            and, optionally, a *value*."""
            pass

        def event(self) -> Event:
            """Return a new :class:`~simpy.events.Event` instance.

            Yielding this event suspends a process until another process
            triggers the event.
            """
            pass

        def all_of(self, events: Iterable[Event]) -> AllOf:
            """Return a :class:`~simpy.events.AllOf` condition for *events*."""
            pass

        def any_of(self, events: Iterable[Event]) -> AnyOf:
            """Return a :class:`~simpy.events.AnyOf` condition for *events*."""
            pass
    else:
        process = BoundClass(Process)
        timeout = BoundClass(Timeout)
        event = BoundClass(Event)
        all_of = BoundClass(AllOf)
        any_of = BoundClass(AnyOf)

    def schedule(self, event: Event, priority: EventPriority=NORMAL, delay: SimTime=0) -> None:
        """Schedule an *event* with a given *priority* and a *delay*."""
        pass

    def peek(self) -> SimTime:
        """Get the time of the next scheduled event. Return
        :data:`~simpy.core.Infinity` if there is no further event."""
        pass

    def step(self) -> None:
        """Process the next event.

        Raise an :exc:`EmptySchedule` if no further events are available.

        """
        pass

    def run(self, until: Optional[Union[SimTime, Event]]=None) -> Optional[Any]:
        """Executes :meth:`step()` until the given criterion *until* is met.

        - If it is ``None`` (which is the default), this method will return
          when there are no further events to be processed.

        - If it is an :class:`~simpy.events.Event`, the method will continue
          stepping until this event has been triggered and will return its
          value.  Raises a :exc:`RuntimeError` if there are no further events
          to be processed and the *until* event was not triggered.

        - If it is a number, the method will continue stepping
          until the environment's time reaches *until*.

        """
        pass===== src/simpy/events.py =====
"""
This module contains the basic event types used in SimPy.

The base class for all events is :class:`Event`. Though it can be directly
used, there are several specialized subclasses of it.

.. autosummary::

    ~simpy.events.Event
    ~simpy.events.Timeout
    ~simpy.events.Process
    ~simpy.events.AnyOf
    ~simpy.events.AllOf

"""
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Callable, Dict, Generator, Iterable, Iterator, List, NewType, Optional, Tuple, TypeVar
from simpy.exceptions import Interrupt
if TYPE_CHECKING:
    from types import FrameType
    from simpy.core import Environment, SimTime
PENDING: object = object()
'Unique object to identify pending values of events.'
EventPriority = NewType('EventPriority', int)
URGENT: EventPriority = EventPriority(0)
'Priority of interrupts and process initialization events.'
NORMAL: EventPriority = EventPriority(1)
'Default priority used by events.'

class Event:
    """An event that may happen at some point in time.

    An event

    - may happen (:attr:`triggered` is ``False``),
    - is going to happen (:attr:`triggered` is ``True``) or
    - has happened (:attr:`processed` is ``True``).

    Every event is bound to an environment *env* and is initially not
    triggered. Events are scheduled for processing by the environment after
    they are triggered by either :meth:`succeed`, :meth:`fail` or
    :meth:`trigger`. These methods also set the *ok* flag and the *value* of
    the event.

    An event has a list of :attr:`callbacks`. A callback can be any callable.
    Once an event gets processed, all callbacks will be invoked with the event
    as the single argument. Callbacks can check if the event was successful by
    examining *ok* and do further processing with the *value* it has produced.

    Failed events are never silently ignored and will raise an exception upon
    being processed. If a callback handles an exception, it must set
    :attr:`defused` to ``True`` to prevent this.

    This class also implements ``__and__()`` (``&``) and ``__or__()`` (``|``).
    If you concatenate two events using one of these operators,
    a :class:`Condition` event is generated that lets you wait for both or one
    of them.

    """
    _ok: bool
    _defused: bool
    _value: Any = PENDING

    def __init__(self, env: Environment):
        self.env = env
        'The :class:`~simpy.core.Environment` the event lives in.'
        self.callbacks: EventCallbacks = []
        'List of functions that are called when the event is processed.'

    def __repr__(self) -> str:
        """Return the description of the event (see :meth:`_desc`) with the id
        of the event."""
        return f'<{self._desc()} object at {id(self):#x}>'

    def _desc(self) -> str:
        """Return a string *Event()*."""
        pass

    @property
    def triggered(self) -> bool:
        """Becomes ``True`` if the event has been triggered and its callbacks
        are about to be invoked."""
        pass

    @property
    def processed(self) -> bool:
        """Becomes ``True`` if the event has been processed (e.g., its
        callbacks have been invoked)."""
        pass

    @property
    def ok(self) -> bool:
        """Becomes ``True`` when the event has been triggered successfully.

        A "successful" event is one triggered with :meth:`succeed()`.

        :raises AttributeError: if accessed before the event is triggered.

        """
        pass

    @property
    def defused(self) -> bool:
        """Becomes ``True`` when the failed event's exception is "defused".

        When an event fails (i.e. with :meth:`fail()`), the failed event's
        `value` is an exception that will be re-raised when the
        :class:`~simpy.core.Environment` processes the event (i.e. in
        :meth:`~simpy.core.Environment.step()`).

        It is also possible for the failed event's exception to be defused by
        setting :attr:`defused` to ``True`` from an event callback. Doing so
        prevents the event's exception from being re-raised when the event is
        processed by the :class:`~simpy.core.Environment`.

        """
        pass

    @property
    def value(self) -> Optional[Any]:
        """The value of the event if it is available.

        The value is available when the event has been triggered.

        Raises :exc:`AttributeError` if the value is not yet available.

        """
        pass

    def trigger(self, event: Event) -> None:
        """Trigger the event with the state and value of the provided *event*.
        Return *self* (this event instance).

        This method can be used directly as a callback function to trigger
        chain reactions.

        """
        pass

    def succeed(self, value: Optional[Any]=None) -> Event:
        """Set the event's value, mark it as successful and schedule it for
        processing by the environment. Returns the event instance.

        Raises :exc:`RuntimeError` if this event has already been triggerd.

        """
        pass

    def fail(self, exception: Exception) -> Event:
        """Set *exception* as the events value, mark it as failed and schedule
        it for processing by the environment. Returns the event instance.

        Raises :exc:`TypeError` if *exception* is not an :exc:`Exception`.

        Raises :exc:`RuntimeError` if this event has already been triggered.

        """
        pass

    def __and__(self, other: Event) -> Condition:
        """Return a :class:`~simpy.events.Condition` that will be triggered if
        both, this event and *other*, have been processed."""
        return Condition(self.env, Condition.all_events, [self, other])

    def __or__(self, other: Event) -> Condition:
        """Return a :class:`~simpy.events.Condition` that will be triggered if
        either this event or *other* have been processed (or even both, if they
        happened concurrently)."""
        return Condition(self.env, Condition.any_events, [self, other])
EventType = TypeVar('EventType', bound=Event)
EventCallback = Callable[[EventType], None]
EventCallbacks = List[EventCallback]

class Timeout(Event):
    """A :class:`~simpy.events.Event` that gets processed after a *delay* has
    passed.

    This event is automatically triggered when it is created.


    """

    def __init__(self, env: Environment, delay: SimTime, value: Optional[Any]=None):
        if delay < 0:
            raise ValueError(f'Negative delay {delay}')
        self.env = env
        self.callbacks: EventCallbacks = []
        self._value = value
        self._delay = delay
        self._ok = True
        env.schedule(self, NORMAL, delay)

    def _desc(self) -> str:
        """Return a string *Timeout(delay[, value=value])*."""
        pass

class Initialize(Event):
    """Initializes a process. Only used internally by :class:`Process`.

    This event is automatically triggered when it is created.

    """

    def __init__(self, env: Environment, process: Process):
        self.env = env
        self.callbacks: EventCallbacks = [process._resume]
        self._value: Any = None
        self._ok = True
        env.schedule(self, URGENT)

class Interruption(Event):
    """Immediately schedules an :class:`~simpy.exceptions.Interrupt` exception
    with the given *cause* to be thrown into *process*.

    This event is automatically triggered when it is created.

    """

    def __init__(self, process: Process, cause: Optional[Any]):
        self.env = process.env
        self.callbacks: EventCallbacks = [self._interrupt]
        self._value = Interrupt(cause)
        self._ok = False
        self._defused = True
        if process._value is not PENDING:
            raise RuntimeError(f'{process} has terminated and cannot be interrupted.')
        if process is self.env.active_process:
            raise RuntimeError('A process is not allowed to interrupt itself.')
        self.process = process
        self.env.schedule(self, URGENT)
ProcessGenerator = Generator[Event, Any, Any]

class Process(Event):
    """Process an event yielding generator.

    A generator (also known as a coroutine) can suspend its execution by
    yielding an event. ``Process`` will take care of resuming the generator
    with the value of that event once it has happened. The exception of failed
    events is thrown into the generator.

    ``Process`` itself is an event, too. It is triggered, once the generator
    returns or raises an exception. The value of the process is the return
    value of the generator or the exception, respectively.

    Processes can be interrupted during their execution by :meth:`interrupt`.

    """

    def __init__(self, env: Environment, generator: ProcessGenerator):
        if not hasattr(generator, 'throw'):
            raise ValueError(f'{generator} is not a generator.')
        self.env = env
        self.callbacks: EventCallbacks = []
        self._generator = generator
        self._target: Event = Initialize(env, self)

    def _desc(self) -> str:
        """Return a string *Process(process_func_name)*."""
        pass

===== src/simpy/resources/base.py =====
"""
Base classes of for SimPy's shared resource types.

:class:`BaseResource` defines the abstract base resource. It supports *get* and
*put* requests, which return :class:`Put` and :class:`Get` events respectively.
These events are triggered once the request has been completed.

"""
from __future__ import annotations
from typing import TYPE_CHECKING, ClassVar, ContextManager, Generic, MutableSequence, Optional, Type, TypeVar, Union
from simpy.core import BoundClass, Environment
from simpy.events import Event, Process
if TYPE_CHECKING:
    from types import TracebackType
ResourceType = TypeVar('ResourceType', bound='BaseResource')

class Put(Event, ContextManager['Put'], Generic[ResourceType]):
    """Gene<response clipped><NOTE>Due to the max output limit, only part of the full response has been shown to you.</NOTE> increase and refuelled cars decrease the amount of gas in the station's
fuel tanks.

"""
from __future__ import annotations
from typing import TYPE_CHECKING, Optional, Union
from simpy.core import BoundClass, Environment
from simpy.resources import base
ContainerAmount = Union[int, float]

class ContainerPut(base.Put):
    """Request to put *amount* of matter into the *container*. The request will
    be triggered once there is enough space in the *container* available.

    Raise a :exc:`ValueError` if ``amount <= 0``.

    """

    def __init__(self, container: Container, amount: ContainerAmount):
        if amount <= 0:
            raise ValueError(f'amount(={amount}) must be > 0.')
        self.amount = amount
        'The amount of matter to be put into the container.'
        super().__init__(container)

class ContainerGet(base.Get):
    """Request to get *amount* of matter from the *container*. The request will
    be triggered once there is enough matter available in the *container*.

    Raise a :exc:`ValueError` if ``amount <= 0``.

    """

    def __init__(self, container: Container, amount: ContainerAmount):
        if amount <= 0:
            raise ValueError(f'amount(={amount}) must be > 0.')
        self.amount = amount
        'The amount of matter to be taken out of the container.'
        super().__init__(container)

class Container(base.BaseResource):
    """Resource containing up to *capacity* of matter which may either be
    continuous (like water) or discrete (like apples). It supports requests to
    put or get matter into/from the container.

    The *env* parameter is the :class:`~simpy.core.Environment` instance the
    container is bound to.

    The *capacity* defines the size of the container. By default, a container
    is of unlimited size. The initial amount of matter is specified by *init*
    and defaults to ``0``.

    Raise a :exc:`ValueError` if ``capacity <= 0``, ``init < 0`` or
    ``init > capacity``.

    """

    def __init__(self, env: Environment, capacity: ContainerAmount=float('inf'), init: ContainerAmount=0):
        if capacity <= 0:
            raise ValueError('"capacity" must be > 0.')
        if init < 0:
            raise ValueError('"init" must be >= 0.')
        if init > capacity:
            raise ValueError('"init" must be <= "capacity".')
        super().__init__(env, capacity)
        self._level = init

    @property
    def level(self) -> ContainerAmount:
        """The current amount of the matter in the container."""
        pass
    if TYPE_CHECKING:

        def put(self, amount: ContainerAmount) -> ContainerPut:
            """Request to put *amount* of matter into the container."""
            pass

        def get(self, amount: ContainerAmount) -> ContainerGet:
            """Request to get *amount* of matter out of the container."""
            pass
    else:
        put = BoundClass(ContainerPut)
        get = BoundClass(ContainerGet)===== src/simpy/resources/store.py =====
"""
Shared resources for storing a possibly unlimited amount of objects supporting
requests for specific objects.

The :class:`Store` operates in a FIFO (first-in, first-out) order. Objects are
retrieved from the store in the order they were put in. The *get* requests of a
:class:`FilterStore` can be customized by a filter to only retrieve objects
matching a given criterion.

"""
from __future__ import annotations
from heapq import heappop, heappush
from typing import TYPE_CHECKING, Any, Callable, List, NamedTuple, Optional, Union
from simpy.core import BoundClass, Environment
from simpy.resources import base

class StorePut(base.Put):
    """Request to put *item* into the *store*. The request is triggered once
    there is space for the item in the store.

    """

    def __init__(self, store: Store, item: Any):
        self.item = item
        'The item to put into the store.'
        super().__init__(store)

class StoreGet(base.Get):
    """Request to get an *item* from the *store*. The request is triggered
    once there is an item available in the store.

    """

class FilterStoreGet(StoreGet):
    """Request to get an *item* from the *store* matching the *filter*. The
    request is triggered once there is such an item available in the store.

    *filter* is a function receiving one item. It should return ``True`` for
    items matching the filter criterion. The default function returns ``True``
    for all items, which makes the request to behave exactly like
    :class:`StoreGet`.

    """

    def __init__(self, resource: FilterStore, filter: Callable[[Any], bool]=lambda item: True):
        self.filter = filter
        'The filter function to filter items in the store.'
        super().__init__(resource)

class Store(base.BaseResource):
    """Resource with *capacity* slots for storing arbitrary objects. By
    default, the *capacity* is unlimited and objects are put and retrieved from
    the store in a first-in first-out order.

    The *env* parameter is the :class:`~simpy.core.Environment` instance the
    container is bound to.

    """

    def __init__(self, env: Environment, capacity: Union[float, int]=float('inf')):
        if capacity <= 0:
            raise ValueError('"capacity" must be > 0.')
        super().__init__(env, capacity)
        self.items: List[Any] = []
        'List of the items available in the store.'
    if TYPE_CHECKING:

        def put(self, item: Any) -> StorePut:
            """Request to put *item* into the store."""
            pass

        def get(self) -> StoreGet:
            """Request to get an *item* out of the store."""
            pass
    else:
        put = BoundClass(StorePut)
        get = BoundClass(StoreGet)

class PriorityItem(NamedTuple):
    """Wrap an arbitrary *item* with an order-able *priority*.

    Pairs a *priority* with an arbitrary *item*. Comparisons of *PriorityItem*
    instances only consider the *priority* attribute, thus supporting use of
    unorderable items in a :class:`PriorityStore` instance.

    """
    priority: Any
    item: Any

    def __lt__(self, other: PriorityItem) -> bool:
        return self.priority < other.priority

class PriorityStore(Store):
    """Resource with *capacity* slots for storing objects in priority order.

    Unlike :class:`Store` which provides first-in first-out discipline,
    :class:`PriorityStore` maintains items in sorted order such that
    the smallest items value are retrieved first from the store.

    All items in a *PriorityStore* instance must be order-able; which is to say
    that items must implement :meth:`~object.__lt__()`. To use unorderable
    items with *PriorityStore*, use :class:`PriorityItem`.

    """

class FilterStore(Store):
    """Resource with *capacity* slots for storing arbitrary objects supporting
    filtered get requests. Like the :class:`Store`, the *capacity* is unlimited
    by default and objects are put and retrieved from the store in a first-in
    first-out order.

    Get requests can be customized with a filter function to only trigger for
    items for which said filter function returns ``True``.

    .. note::

        In contrast to :class:`Store`, get requests of a :class:`FilterStore`
        won't necessarily be triggered in the same order they were issued.

        *Example:* The store is empty. *Process 1* tries to get an item of type
        *a*, *Process 2* an item of type *b*. Another process puts one item of
        type *b* into the store. Though *Process 2* made his request after
        *Process 1*, it will receive that new item because *Process 1* doesn't
        want it.

    """
    if TYPE_CHECKING:

        def get(self, filter: Callable[[Any], bool]=lambda item: True) -> FilterStoreGet:
            """Request to get an *item*, for which *filter* returns ``True``,
            out of the store."""
            pass
    else:
        get = BoundClass(FilterStoreGet)===== src/simpy/exceptions.py =====
"""
SimPy specific exceptions.

"""
from __future__ import annotations
from typing import Any, Optional

class SimPyException(Exception):
    """Base class for all SimPy specific exceptions."""

class Interrupt(SimPyException):
    """Exception thrown into a process if it is interrupted (see
    :func:`~simpy.events.Process.interrupt()`).

    :attr:`cause` provides the reason for the interrupt, if any.

    If a process is interrupted concurrently, all interrupts will be thrown
    into the process in the same order as they occurred.


    """

    def __init__(self, cause: Optional[Any]):
        super().__init__(cause)

    def __str__(self) -> str:
        return f'{self.__class__.__name__}({self.cause!r})'

    @property
    def cause(self) -> Optional[Any]:
        """The cause of the interrupt or ``None`` if no cause was provided."""
        pass===== src/simpy/util.py =====
"""
A collection of utility functions:

.. autosummary::
   start_delayed

"""
from typing import Generator
from simpy.core import Environment, SimTime
from simpy.events import Event, Process, ProcessGenerator

def start_delayed(env: Environment, generator: ProcessGenerator, delay: SimTime) -> Process:
    """Return a helper process that starts another process for *generator*
    after a certain *delay*.

    :meth:`~simpy.core.Environment.process()` starts a process at the current
    simulation time. This helper allows you to start a process after a delay of
    *delay* simulation time units::

        >>> from simpy import Environment
        >>> from simpy.util import start_delayed
        >>> def my_process(env, x):
        ...     print(f'{env.now}, {x}')
        ...     yield env.timeout(1)
        ...
        >>> env = Environment()
        >>> proc = start_delayed(env, my_process(env, 3), 5)
        >>> env.run()
        5, 3

    Raise a :exc:`ValueError` if ``delay <= 0``.

    """
    pass

def subscribe_at(event: Event) -> None:
    """Register at the *event* to receive an interrupt when it occurs.

    The most common use case for this is to pass
    a :class:`~simpy.events.Process` to get notified when it terminates.

    Raise a :exc:`RuntimeError` if ``event`` has already occurred.

    """
    pass===== src/simpy/rt.py =====
"""Execution environment for events that synchronizes passing of time
with the real-time (aka *wall-clock time*).

"""
from time import monotonic, sleep
from simpy.core import EmptySchedule, Environment, Infinity, SimTime

class RealtimeEnvironment(Environment):
    """Execution environment for an event-based simulation which is
    synchronized with the real-time (also known as wall-clock time). A time
    step will take *factor* seconds of real time (one second by default).
    A step from ``0`` to ``3`` with a ``factor=0.5`` will, for example, take at
    least
    1.5 seconds.

    The :meth:`step()` method will raise a :exc:`RuntimeError` if a time step
    took too long to compute. This behaviour can be disabled by setting
    *strict* to ``False``.

    """

    def __init__(self, initial_time: SimTime=0, factor: float=1.0, strict: bool=True):
        Environment.__init__(self, initial_time)
        self.env_start = initial_time
        self.real_start = monotonic()
        self._factor = factor
        self._strict = strict

    @property
    def factor(self) -> float:
        """Scaling factor of the real-time."""
        pass

    @property
    def strict(self) -> bool:
        """Running mode of the environment. :meth:`step()` will raise a
        :exc:`RuntimeError` if this is set to ``True`` and the processing of
        events takes too long."""
        pass

    def sync(self) -> None:
        """Synchronize the internal time with the current wall-clock time.

        This can be useful to prevent :meth:`step()` from raising an error if
        a lot of time passes between creating the RealtimeEnvironment and
        calling :meth:`run()` or :meth:`step()`.

        """
        pass

    def step(self) -> None:
        """Process the next event after enough real-time has passed for the
        event to happen.

        The delay is scaled according to the real-time :attr:`factor`. With
        :attr:`strict` mode enabled, a :exc:`RuntimeError` will be raised, if
        the event is processed too slowly.

        """
        pass===== src/simpy/__init__.py =====
"""
The ``simpy`` module aggregates SimPy's most used components into a single
namespace. This is purely for convenience. You can of course also access
everything (and more!) via their actual submodules.

The following tables list all the available components in this module.

{toc}

"""
from __future__ import annotations

import importlib.metadata
from typing import Tuple, Type

from simpy.core import Environment
from simpy.events import AllOf, AnyOf, Event, Process, Timeout
from simpy.exceptions import Interrupt, SimPyException
from simpy.resources.container import Container
from simpy.resources.resource import PreemptiveResource, PriorityResource, Resource
from simpy.resources.store import FilterStore, PriorityItem, PriorityStore, Store
from simpy.rt import RealtimeEnvironment

__all__ = [
    'AllOf',
    'AnyOf',
    'Container',
    'Environment',
    'Event',
    'FilterStore',
    'Interrupt',
    'PreemptiveResource',
    'PriorityItem',
    'PriorityResource',
    'PriorityStore',
    'Process',
    'RealtimeEnvironment',
    'Resource',
    'SimPyException',
    'Store',
    'Timeout',
]


def _compile_toc(
    entries: Tuple[Tuple[str, Tuple[Type, ...]], ...],
    section_marker: str = '=',
) -> str:
    """Compiles a list of sections with objects into sphinx formatted
    autosummary directives."""
    toc = ''
    for section, objs in entries:
        toc += '\n\n'
        toc += f'{section}\n'
        toc += f'{section_marker * len(section)}\n\n'
        toc += '.. autosummary::\n\n'
        for obj in objs:
            toc += f'    ~{obj.__module__}.{obj.__name__}\n'
    return toc


_toc = (
    (
        'Environments',
        (
            Environment,
            RealtimeEnvironment,
        ),
    ),
    (
        'Events',
        (
            Event,
            Timeout,
            Process,
            AllOf,
            AnyOf,
            Interrupt,
        ),
    ),
    (
        'Resources',
        (
            Resource,
            PriorityResource,
            PreemptiveResource,
            Container,
            Store,
            PriorityItem,
            PriorityStore,
            FilterStore,
        ),
    ),
    ('Exceptions', (SimPyException, Interrupt)),
)

# Use the _toc to keep the documentation and the implementation in sync.
if __doc__:
    __doc__ = __doc__.format(toc=_compile_toc(_toc))
    assert set(__all__) == {obj.__name__ for _, objs in _toc for obj in objs}

try:
    __version__ = importlib.metadata.version('simpy')
except importlib.metadata.PackageNotFoundError:
    # package is not installed
    pass
[The command completed with exit code 0.]
[Current working directory: /workspace/simpy]
[Python interpreter: /usr/bin/python]
[Command finished with exit code 0]