# Path: envlogger/step_data.py
# class StepData(NamedTuple):
# 
# Path: envlogger/backends/backend_reader.py
# T = TypeVar('T')
# class _SequenceAdapter(Generic[T], Sequence[T]):
# class BackendReader(metaclass=abc.ABCMeta):
#   def __init__(self, count: int, get_nth_item: Callable[[int], T]):
#   def __getitem__(self, index: Union[int, slice]) -> Union[T, List[T]]:
#   def __len__(self) -> int:
#   def __iter__(self) -> Iterator[T]:
#   def __next__(self) -> T:
#   def __init__(self):
#   def copy(self) -> 'BackendReader':
#   def _copy(self) -> 'BackendReader':
#   def _init_visitors(self):
#   def _get_nth_step(self, i: int) -> step_data.StepData:
#   def _get_num_steps(self) -> int:
#   def _get_num_episodes(self) -> int:
#   def _get_nth_episode_info(self,
#                             i: int,
#                             include_metadata: bool = False
#                            ) -> episode_info.EpisodeInfo:
#   def _get_nth_episode(self, i: int) -> Sequence[step_data.StepData]:
#     def get_nth_step_from_episode(j: int):
#   def _get_nth_episode_metadata(self, i: int) -> Optional[Any]:
#   def __enter__(self):
#   def __exit__(self, exc_type, exc_value, tb):
#   def __del__(self):
#   def close(self) -> None:
#   def metadata(self) -> Dict[str, Any]:
#   def episodes(self) -> Sequence[Sequence[step_data.StepData]]:
#   def episode_metadata(self) -> Sequence[Optional[Any]]:
#   def steps(self) -> Sequence[step_data.StepData]:
# 
# Path: envlogger/backends/backend_writer.py
# class BackendWriter(metaclass=abc.ABCMeta):
#   def __init__(self,
#                metadata: Optional[Dict[str, Any]] = None,
#                scheduler: Optional[schedulers.Scheduler] = None):
#   def record_step(self, data: step_data.StepData, is_new_episode: bool) -> None:
#   def set_episode_metadata(self, data: Any) -> None:
#   def _record_step(self, data: step_data.StepData,
#                    is_new_episode: bool) -> None:
#   def close(self) -> None:
#   def __del__(self):
#   def metadata(self):


import copy
from typing import Any
from envlogger import step_data
from envlogger.backends import backend_reader
from envlogger.backends import backend_writer
from envlogger.backends.python import episode_info
    self.episode_start_indices = []

  def _record_step(self, data: step_data.StepData,
                   is_new_episode: bool) -> None:
    if is_new_episode:
      self.episode_start_indices.append(len(self.steps))
    self.steps.append(data)

  def set_episode_metadata(self, data: Any) -> None:
    current_episode = len(self.episode_start_indices)
    if current_episode > 0:
      self.episode_metadata[current_episode] = data

  def close(self) -> None:
    pass


class InMemoryBackendReader(backend_reader.BackendReader):
  """Reader that reads data from an InMemoryBackend."""

  def __init__(self, in_memory_backend_writer: InMemoryBackendWriter):
    self._backend = in_memory_backend_writer
    super().__init__()

  def _copy(self) -> 'InMemoryBackendReader':
    return copy.deepcopy(self)

  def close(self) -> None:
    pass


# Path: envlogger/step_data.py
# class StepData(NamedTuple):
# 
# Path: envlogger/backends/backend_reader.py
# T = TypeVar('T')
# class _SequenceAdapter(Generic[T], Sequence[T]):
# class BackendReader(metaclass=abc.ABCMeta):
#   def __init__(self, count: int, get_nth_item: Callable[[int], T]):
#   def __getitem__(self, index: Union[int, slice]) -> Union[T, List[T]]:
#   def __len__(self) -> int:
#   def __iter__(self) -> Iterator[T]:
#   def __next__(self) -> T:
#   def __init__(self):
#   def copy(self) -> 'BackendReader':
#   def _copy(self) -> 'BackendReader':
#   def _init_visitors(self):
#   def _get_nth_step(self, i: int) -> step_data.StepData:
#   def _get_num_steps(self) -> int:
#   def _get_num_episodes(self) -> int:
#   def _get_nth_episode_info(self,
#                             i: int,
#                             include_metadata: bool = False
#                            ) -> episode_info.EpisodeInfo:
#   def _get_nth_episode(self, i: int) -> Sequence[step_data.StepData]:
#     def get_nth_step_from_episode(j: int):
#   def _get_nth_episode_metadata(self, i: int) -> Optional[Any]:
#   def __enter__(self):
#   def __exit__(self, exc_type, exc_value, tb):
#   def __del__(self):
#   def close(self) -> None:
#   def metadata(self) -> Dict[str, Any]:
#   def episodes(self) -> Sequence[Sequence[step_data.StepData]]:
#   def episode_metadata(self) -> Sequence[Optional[Any]]:
#   def steps(self) -> Sequence[step_data.StepData]:
# 
# Path: envlogger/backends/backend_writer.py
# class BackendWriter(metaclass=abc.ABCMeta):
#   def __init__(self,
#                metadata: Optional[Dict[str, Any]] = None,
#                scheduler: Optional[schedulers.Scheduler] = None):
#   def record_step(self, data: step_data.StepData, is_new_episode: bool) -> None:
#   def set_episode_metadata(self, data: Any) -> None:
#   def _record_step(self, data: step_data.StepData,
#                    is_new_episode: bool) -> None:
#   def close(self) -> None:
#   def __del__(self):
#   def metadata(self):


# Path: envlogger/backends/in_memory_backend.py
import copy
from typing import Any
from envlogger import step_data
from envlogger.backends import backend_reader
from envlogger.backends import backend_writer
from envlogger.backends.python import episode_info

    self.episode_start_indices = []

  def _record_step(self, data: step_data.StepData,
                   is_new_episode: bool) -> None:
    if is_new_episode:
      self.episode_start_indices.append(len(self.steps))
    self.steps.append(data)

  def set_episode_metadata(self, data: Any) -> None:
    current_episode = len(self.episode_start_indices)
    if current_episode > 0:
      self.episode_metadata[current_episode] = data

  def close(self) -> None:
    pass


class InMemoryBackendReader(backend_reader.BackendReader):
  """Reader that reads data from an InMemoryBackend."""

  def __init__(self, in_memory_backend_writer: InMemoryBackendWriter):
    self._backend = in_memory_backend_writer
    super().__init__()

  def _copy(self) -> 'InMemoryBackendReader':
    return copy.deepcopy(self)

  def close(self) -> None:
    pass


  def _get_nth_step(self, i: int) -> step_data.StepData: