docstr: Tests creation of a scucessor of a `SingleAgentEpisode`.
  
  This test makes sure that when creating a successor the successor's
  data is coherent with the episode that should be succeeded.
  Observation and info are available before each timestep; therefore
  these data is carried over to the successor.
docstr_tok: ["Tests","creation","of","a","scucessor","of","a","`","SingleAgentEpisode","`",".","This","test","makes","sure","that","when","creating","a","successor","the","successor's","data","is","coherent","with","the","episode","that","should","be","succeeded",".","Observation","and","info","are","available","before","each","timestep",";","therefore","these","data","is","carried","over","to","the","successor","."]
code: def test_cut(self):
      """Tests creation of a scucessor of a `SingleAgentEpisode`.
  
      This test makes sure that when creating a successor the successor's
      data is coherent with the episode that should be succeeded.
      Observation and info are available before each timestep; therefore
      these data is carried over to the successor.
      """
  
      # Create an empty episode.
      episode_1 = SingleAgentEpisode()
      # Create an environment.
      env = TestEnv()
      # Add initial observation.
      init_obs, init_info = env.reset()
      episode_1.add_env_reset(observation=init_obs, infos=init_info)
      # Sample 100 steps.
      for i in range(100):
          action = i
          obs, reward, terminated, truncated, info = env.step(action)
          episode_1.add_env_step(
              observation=obs,
              action=action,
              reward=reward,
              infos=info,
              terminated=terminated,
              truncated=truncated,
              extra_model_outputs={"extra": np.random.random(1)},
          )
  
      # Assert that the episode has indeed 100 timesteps.
      self.assertTrue(episode_1.t == 100)
  
      # Create a successor.
      episode_2 = episode_1.cut()
      # Assert that it has the same id.
      self.assertEqual(episode_1.id_, episode_2.id_)
      # Assert that the timestep starts at the end of the last episode.
      self.assertTrue(episode_1.t == episode_2.t == episode_2.t_started)
      # Assert that the last observation of `episode_1` is the first of
      # `episode_2`.
      self.assertTrue(
          episode_1.observations[-1] == episode_2.observations[0]
      )
      # Assert that the last info of `episode_1` is the first of episode_2`.
      self.assertTrue(episode_1.infos[-1] == episode_2.infos[0])
  
      # Test immutability.
      action = 100
      obs, reward, terminated, truncated, info = env.step(action)
      episode_2.add_env_step(
          observation=obs,
          action=action,
          reward=reward,
          infos=info,
          terminated=terminated,
          truncated=truncated,
          extra_model_outputs={"extra": np.random.random(1)},
      )
      # Assert that this does not change also the predecessor's data.
      self.assertFalse(
          len(episode_1.observations) == len(episode_2.observations)
      )
  
imports: from collections import defaultdict
  from typing import Any, Dict, Optional, SupportsFloat, Tuple
  import unittest
  import gymnasium
  from gymnasium.core import ActType, ObsType
  import numpy
  from ray.rllib.env.single_agent_episode import SingleAgentEpisode
  from ray.rllib.utils.test_utils import check
label_desc: Use image node_id 4 for calling the TestSingelAgentEpisode obj's underlying member method code with example usage: obj.test_cut() without return types