diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 31245ea2c..e48b065e4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -15,4 +15,4 @@ jobs: --build-arg PYTHON_VERSION=${{ matrix.python-version }} \ --tag gym-docker . - name: Run tests - run: docker run gym-docker pytest --forked --import-mode=append + run: docker run gym-docker pytest --import-mode=append diff --git a/gym/__init__.py b/gym/__init__.py index b44d1b419..42f0bd3fc 100644 --- a/gym/__init__.py +++ b/gym/__init__.py @@ -14,15 +14,22 @@ from gym import vector from gym import wrappers import os - +import sys __all__ = ["Env", "Space", "Wrapper", "make", "spec", "register"] +# Initializing pygame initializes audio connections through SDL. SDL uses alsa by default on all Linux systems +# SDL connecting to alsa frequently create these giant lists of warnings every time you import an environment using +# pygame +# DSP is far more benign (and should probably be the default in SDL anyways) + +if sys.platform.startswith("linux"): + os.environ["SDL_AUDIODRIVER"] = "dsp" + os.environ["PYGAME_HIDE_SUPPORT_PROMPT"] = "hide" try: import gym_notices.notices as notices - import sys # print version warning if necessary notice = notices.notices.get(__version__) diff --git a/gym/envs/box2d/car_racing.py b/gym/envs/box2d/car_racing.py index 846d3748c..faa3a19f5 100644 --- a/gym/envs/box2d/car_racing.py +++ b/gym/envs/box2d/car_racing.py @@ -170,6 +170,8 @@ def __init__(self, verbose=1, lap_complete_percent=0.95): shape=polygonShape(vertices=[(0, 0), (1, 0), (1, -1), (0, -1)]) ) + # This will throw a warning in tests/envs/test_envs in utils/env_checker.py as the space is not symmetric + # or normalised however this is not possible here so ignore self.action_space = spaces.Box( np.array([-1, 0, 0]).astype(np.float32), np.array([+1, +1, +1]).astype(np.float32), @@ -604,9 +606,9 @@ def _create_image_array(self, screen, size): ) def close(self): + pygame.quit() if self.screen is not None: pygame.display.quit() - pygame.quit() self.isopen = False diff --git a/gym/envs/classic_control/pendulum.py b/gym/envs/classic_control/pendulum.py index 525186e1d..f1526ff8e 100644 --- a/gym/envs/classic_control/pendulum.py +++ b/gym/envs/classic_control/pendulum.py @@ -95,6 +95,9 @@ def __init__(self, g=10.0): self.screen_dim = 500 high = np.array([1.0, 1.0, self.max_speed], dtype=np.float32) + # This will throw a warning in tests/envs/test_envs in utils/env_checker.py as the space is not symmetric + # or normalised as max_torque == 2 by default. Ignoring the issue here as the default settings are too old + # to update to follow the openai gym api self.action_space = spaces.Box( low=-self.max_torque, high=self.max_torque, shape=(1,), dtype=np.float32 ) @@ -187,7 +190,7 @@ def render(self, mode="human"): scale_img = pygame.transform.smoothscale( img, (scale * np.abs(self.last_u) / 2, scale * np.abs(self.last_u) / 2) ) - is_flip = self.last_u > 0 + is_flip = bool(self.last_u > 0) scale_img = pygame.transform.flip(scale_img, is_flip, True) self.surf.blit( scale_img, diff --git a/gym/envs/toy_text/cliffwalking.py b/gym/envs/toy_text/cliffwalking.py index cfa3b645f..b28cf0510 100644 --- a/gym/envs/toy_text/cliffwalking.py +++ b/gym/envs/toy_text/cliffwalking.py @@ -67,7 +67,7 @@ def __init__(self): self.nA = 4 # Cliff Location - self._cliff = np.zeros(self.shape, dtype=np.bool) + self._cliff = np.zeros(self.shape, dtype=bool) self._cliff[3, 1:-1] = True # Calculate transition probabilities and rewards diff --git a/gym/spaces/dict.py b/gym/spaces/dict.py index fe12b3575..54f71a063 100644 --- a/gym/spaces/dict.py +++ b/gym/spaces/dict.py @@ -41,7 +41,7 @@ def __init__( self, spaces: dict[str, Space] | None = None, seed: dict | int | None = None, - **spaces_kwargs: Space + **spaces_kwargs: Space, ): assert (spaces is None) or ( not spaces_kwargs diff --git a/gym/spaces/discrete.py b/gym/spaces/discrete.py index 6c09e5718..e53731841 100644 --- a/gym/spaces/discrete.py +++ b/gym/spaces/discrete.py @@ -25,7 +25,7 @@ def __init__(self, n: int, seed: Optional[int] = None, start: int = 0): super().__init__((), np.int64, seed) def sample(self) -> int: - return self.start + self.np_random.randint(self.n) + return int(self.start + self.np_random.integers(self.n)) def contains(self, x) -> bool: if isinstance(x, int): diff --git a/gym/vector/async_vector_env.py b/gym/vector/async_vector_env.py index c7c1bf319..651c079f8 100644 --- a/gym/vector/async_vector_env.py +++ b/gym/vector/async_vector_env.py @@ -627,7 +627,7 @@ def _raise_if_errors(self, successes): raise exctype(value) def __del__(self): - if not getattr(self, "closed", True): + if not getattr(self, "closed", True) and hasattr(self, "_state"): self.close(terminate=True) diff --git a/gym/wrappers/record_video.py b/gym/wrappers/record_video.py index 3bf48070b..c75c7d6c4 100644 --- a/gym/wrappers/record_video.py +++ b/gym/wrappers/record_video.py @@ -116,3 +116,9 @@ def close_video_recorder(self) -> None: self.video_recorder.close() self.recording = False self.recorded_frames = 1 + + def close(self): + self.close_video_recorder() + + def __del__(self): + self.close_video_recorder() diff --git a/tests/envs/test_envs.py b/tests/envs/test_envs.py index 3f99d8d3c..df26e607b 100644 --- a/tests/envs/test_envs.py +++ b/tests/envs/test_envs.py @@ -10,6 +10,9 @@ # This runs a smoketest on each official registered env. We may want # to try also running environments which are not officially registered # envs. +@pytest.mark.filterwarnings( + "ignore:.*We recommend you to use a symmetric and normalized Box action space.*" +) @pytest.mark.parametrize("spec", spec_list) def test_env(spec): # Capture warnings @@ -74,7 +77,7 @@ def test_reset_info(spec): # Run a longer rollout on some environments def test_random_rollout(): - for env in [envs.make("CartPole-v0"), envs.make("FrozenLake-v1")]: + for env in [envs.make("CartPole-v1"), envs.make("FrozenLake-v1")]: agent = lambda ob: env.action_space.sample() ob = env.reset() for _ in range(10): diff --git a/tests/envs/test_registration.py b/tests/envs/test_registration.py index 2d5d30cd1..a4a7933f8 100644 --- a/tests/envs/test_registration.py +++ b/tests/envs/test_registration.py @@ -61,8 +61,8 @@ def register_some_envs(): def test_make(): - env = envs.make("CartPole-v0") - assert env.spec.id == "CartPole-v0" + env = envs.make("CartPole-v1") + assert env.spec.id == "CartPole-v1" assert isinstance(env.unwrapped, cartpole.CartPoleEnv) @@ -164,6 +164,10 @@ def test_make_with_kwargs(): assert env.arg3 == "override_arg3" +@pytest.mark.filterwarnings( + "ignore:.*The environment Humanoid-v0 is out of date. You should consider upgrading to " + "version `v3` with the environment ID `Humanoid-v3`.*" +) def test_make_deprecated(): try: envs.make("Humanoid-v0") @@ -174,8 +178,8 @@ def test_make_deprecated(): def test_spec(): - spec = envs.spec("CartPole-v0") - assert spec.id == "CartPole-v0" + spec = envs.spec("CartPole-v1") + assert spec.id == "CartPole-v1" def test_spec_with_kwargs(): diff --git a/tests/spaces/test_spaces.py b/tests/spaces/test_spaces.py index 0af15b80c..ace4ff4e0 100644 --- a/tests/spaces/test_spaces.py +++ b/tests/spaces/test_spaces.py @@ -19,7 +19,11 @@ Tuple( [ Discrete(5), - Box(low=np.array([0, 0]), high=np.array([1, 5]), dtype=np.float32), + Box( + low=np.array([0.0, 0.0]), + high=np.array([1.0, 5.0]), + dtype=np.float64, + ), ] ), Tuple((Discrete(5), Discrete(2), Discrete(2))), @@ -30,7 +34,9 @@ { "position": Discrete(5), "velocity": Box( - low=np.array([0, 0]), high=np.array([1, 5]), dtype=np.float32 + low=np.array([0.0, 0.0]), + high=np.array([1.0, 5.0]), + dtype=np.float64, ), } ), @@ -61,13 +67,17 @@ def test_roundtripping(space): [ Discrete(3), Discrete(5, start=-2), - Box(low=np.array([-10, 0]), high=np.array([10, 10]), dtype=np.float32), + Box(low=np.array([-10.0, 0.0]), high=np.array([10.0, 10.0]), dtype=np.float64), Box(low=-np.inf, high=np.inf, shape=(1, 3)), Tuple([Discrete(5), Discrete(10)]), Tuple( [ Discrete(5), - Box(low=np.array([0, 0]), high=np.array([1, 5]), dtype=np.float32), + Box( + low=np.array([0.0, 0.0]), + high=np.array([1.0, 5.0]), + dtype=np.float64, + ), ] ), Tuple((Discrete(5), Discrete(2), Discrete(2))), @@ -78,7 +88,9 @@ def test_roundtripping(space): { "position": Discrete(5), "velocity": Box( - low=np.array([0, 0]), high=np.array([1, 5]), dtype=np.float32 + low=np.array([0.0, 0.0]), + high=np.array([1.0, 5.0]), + dtype=np.float64, ), } ), @@ -98,8 +110,14 @@ def test_equality(space): (MultiDiscrete([2, 2, 100]), MultiDiscrete([2, 2, 8])), (MultiBinary(8), MultiBinary(7)), ( - Box(low=np.array([-10, 0]), high=np.array([10, 10]), dtype=np.float32), - Box(low=np.array([-10, 0]), high=np.array([10, 9]), dtype=np.float32), + Box( + low=np.array([-10.0, 0.0]), + high=np.array([10.0, 10.0]), + dtype=np.float64, + ), + Box( + low=np.array([-10.0, 0.0]), high=np.array([10.0, 9.0]), dtype=np.float64 + ), ), ( Box(low=-np.inf, high=0.0, shape=(2, 1)), @@ -156,7 +174,11 @@ def test_sample(space): [ (Discrete(5), MultiBinary(5)), ( - Box(low=np.array([-10, 0]), high=np.array([10, 10]), dtype=np.float32), + Box( + low=np.array([-10.0, 0.0]), + high=np.array([10.0, 10.0]), + dtype=np.float64, + ), MultiDiscrete([2, 2, 8]), ), ( @@ -247,7 +269,7 @@ def test_box_dtype_check(): space = Box(0, 2, tuple(), dtype=np.float32) # casting will match the correct type - assert space.contains(0.5) + assert space.contains(np.array(0.5, dtype=np.float32)) # float64 is not in float32 space assert not space.contains(np.array(0.5)) @@ -264,7 +286,11 @@ def test_box_dtype_check(): Tuple( [ Discrete(5), - Box(low=np.array([0, 0]), high=np.array([1, 5]), dtype=np.float32), + Box( + low=np.array([0.0, 0.0]), + high=np.array([1.0, 5.0]), + dtype=np.float64, + ), ] ), Tuple((Discrete(5), Discrete(2), Discrete(2))), @@ -274,7 +300,9 @@ def test_box_dtype_check(): { "position": Discrete(5), "velocity": Box( - low=np.array([0, 0]), high=np.array([1, 5]), dtype=np.float32 + low=np.array([0.0, 0.0]), + high=np.array([1.0, 5.0]), + dtype=np.float64, ), } ), @@ -317,7 +345,11 @@ def sample_equal(sample1, sample2): Tuple( [ Discrete(5), - Box(low=np.array([0, 0]), high=np.array([1, 5]), dtype=np.float32), + Box( + low=np.array([0.0, 0.0]), + high=np.array([1.0, 5.0]), + dtype=np.float64, + ), ] ), Tuple((Discrete(5), Discrete(2), Discrete(2))), @@ -327,7 +359,9 @@ def sample_equal(sample1, sample2): { "position": Discrete(5), "velocity": Box( - low=np.array([0, 0]), high=np.array([1, 5]), dtype=np.float32 + low=np.array([0.0, 0.0]), + high=np.array([1.0, 5.0]), + dtype=np.float64, ), } ), @@ -353,7 +387,11 @@ def test_seed_reproducibility(space): Tuple( [ Discrete(5), - Box(low=np.array([0, 0]), high=np.array([1, 5]), dtype=np.float32), + Box( + low=np.array([0.0, 0.0]), + high=np.array([1.0, 5.0]), + dtype=np.float64, + ), ] ), Tuple((Discrete(5), Discrete(2), Discrete(2))), @@ -361,7 +399,9 @@ def test_seed_reproducibility(space): { "position": Discrete(5), "velocity": Box( - low=np.array([0, 0]), high=np.array([1, 5]), dtype=np.float32 + low=np.array([0.0, 0.0]), + high=np.array([1.0, 5.0]), + dtype=np.float64, ), } ), @@ -580,7 +620,7 @@ def test_discrete_legacy_state_pickling(): Tuple( [ Discrete(5), - Box(low=np.array([0, 0]), high=np.array([1, 5]), dtype=np.float32), + Box(low=np.array([0.0, 0.0]), high=np.array([1, 5]), dtype=np.float64), ] ), Tuple((Discrete(5), Discrete(2), Discrete(2))), @@ -591,7 +631,7 @@ def test_discrete_legacy_state_pickling(): { "position": Discrete(5), "velocity": Box( - low=np.array([0, 0]), high=np.array([1, 5]), dtype=np.float32 + low=np.array([0.0, 0.0]), high=np.array([1, 5]), dtype=np.float64 ), } ), diff --git a/tests/spaces/test_utils.py b/tests/spaces/test_utils.py index 7c231c91b..4797127cc 100644 --- a/tests/spaces/test_utils.py +++ b/tests/spaces/test_utils.py @@ -14,7 +14,7 @@ Tuple( [ Discrete(5), - Box(low=np.array([0, 0]), high=np.array([1, 5]), dtype=np.float32), + Box(low=np.array([0.0, 0.0]), high=np.array([1.0, 5.0]), dtype=np.float64), ] ), Tuple((Discrete(5), Discrete(2), Discrete(2))), @@ -24,7 +24,7 @@ { "position": Discrete(5), "velocity": Box( - low=np.array([0, 0]), high=np.array([1, 5]), dtype=np.float32 + low=np.array([0.0, 0.0]), high=np.array([1.0, 5.0]), dtype=np.float64 ), } ), diff --git a/tests/vector/test_spaces.py b/tests/vector/test_spaces.py index 4415c405b..0999ff6bf 100644 --- a/tests/vector/test_spaces.py +++ b/tests/vector/test_spaces.py @@ -8,7 +8,7 @@ expected_batch_spaces_4 = [ Box(low=-1.0, high=1.0, shape=(4,), dtype=np.float64), - Box(low=0.0, high=10.0, shape=(4, 1), dtype=np.float32), + Box(low=0.0, high=10.0, shape=(4, 1), dtype=np.float64), Box( low=np.array( [[-1.0, 0.0, 0.0], [-1.0, 0.0, 0.0], [-1.0, 0.0, 0.0], [-1.0, 0.0, 0.0]] @@ -16,7 +16,7 @@ high=np.array( [[1.0, 1.0, 1.0], [1.0, 1.0, 1.0], [1.0, 1.0, 1.0], [1.0, 1.0, 1.0]] ), - dtype=np.float32, + dtype=np.float64, ), Box( low=np.array( @@ -28,7 +28,7 @@ ] ), high=np.ones((4, 2, 2)), - dtype=np.float32, + dtype=np.float64, ), Box(low=0, high=255, shape=(4,), dtype=np.uint8), Box(low=0, high=255, shape=(4, 32, 32, 3), dtype=np.uint8), @@ -41,7 +41,7 @@ Box( low=np.array([[0.0, -1.0], [0.0, -1.0], [0.0, -1.0], [0.0, -1]]), high=np.array([[1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0]]), - dtype=np.float32, + dtype=np.float64, ), ) ), @@ -54,7 +54,7 @@ Dict( { "position": MultiDiscrete([23, 23, 23, 23]), - "velocity": Box(low=0.0, high=1.0, shape=(4, 1), dtype=np.float32), + "velocity": Box(low=0.0, high=1.0, shape=(4, 1), dtype=np.float64), } ), Dict( diff --git a/tests/vector/utils.py b/tests/vector/utils.py index f91450bdc..cfdf493b1 100644 --- a/tests/vector/utils.py +++ b/tests/vector/utils.py @@ -8,12 +8,12 @@ spaces = [ Box(low=np.array(-1.0), high=np.array(1.0), dtype=np.float64), - Box(low=np.array([0.0]), high=np.array([10.0]), dtype=np.float32), + Box(low=np.array([0.0]), high=np.array([10.0]), dtype=np.float64), Box( - low=np.array([-1.0, 0.0, 0.0]), high=np.array([1.0, 1.0, 1.0]), dtype=np.float32 + low=np.array([-1.0, 0.0, 0.0]), high=np.array([1.0, 1.0, 1.0]), dtype=np.float64 ), Box( - low=np.array([[-1.0, 0.0], [0.0, -1.0]]), high=np.ones((2, 2)), dtype=np.float32 + low=np.array([[-1.0, 0.0], [0.0, -1.0]]), high=np.ones((2, 2)), dtype=np.float64 ), Box(low=0, high=255, shape=(), dtype=np.uint8), Box(low=0, high=255, shape=(32, 32, 3), dtype=np.uint8), @@ -23,7 +23,7 @@ Tuple( ( Discrete(7), - Box(low=np.array([0.0, -1.0]), high=np.array([1.0, 1.0]), dtype=np.float32), + Box(low=np.array([0.0, -1.0]), high=np.array([1.0, 1.0]), dtype=np.float64), ) ), MultiDiscrete([11, 13, 17]), @@ -32,7 +32,7 @@ { "position": Discrete(23), "velocity": Box( - low=np.array([0.0]), high=np.array([1.0]), dtype=np.float32 + low=np.array([0.0]), high=np.array([1.0]), dtype=np.float64 ), } ), diff --git a/tests/wrappers/test_normalize.py b/tests/wrappers/test_normalize.py index b1ab68f74..40af999f2 100644 --- a/tests/wrappers/test_normalize.py +++ b/tests/wrappers/test_normalize.py @@ -14,7 +14,7 @@ class DummyRewardEnv(gym.Env): def __init__(self, return_reward_idx=0): self.action_space = gym.spaces.Discrete(2) self.observation_space = gym.spaces.Box( - low=np.array([-1.0]), high=np.array([1.0]) + low=np.array([-1.0]), high=np.array([1.0]), dtype=np.float64 ) self.returned_rewards = [0, 1, 2, 3, 4] self.return_reward_idx = return_reward_idx diff --git a/tests/wrappers/test_record_episode_statistics.py b/tests/wrappers/test_record_episode_statistics.py index e78633d01..5960ed036 100644 --- a/tests/wrappers/test_record_episode_statistics.py +++ b/tests/wrappers/test_record_episode_statistics.py @@ -6,7 +6,7 @@ from gym.wrappers import RecordEpisodeStatistics -@pytest.mark.parametrize("env_id", ["CartPole-v0", "Pendulum-v1"]) +@pytest.mark.parametrize("env_id", ["CartPole-v1", "Pendulum-v1"]) @pytest.mark.parametrize("deque_size", [2, 5]) def test_record_episode_statistics(env_id, deque_size): env = gym.make(env_id) @@ -42,7 +42,7 @@ def test_record_episode_statistics_reset_info(): ("num_envs", "asynchronous"), [(1, False), (1, True), (4, False), (4, True)] ) def test_record_episode_statistics_with_vectorenv(num_envs, asynchronous): - envs = gym.vector.make("CartPole-v0", num_envs=num_envs, asynchronous=asynchronous) + envs = gym.vector.make("CartPole-v1", num_envs=num_envs, asynchronous=asynchronous) envs = RecordEpisodeStatistics(envs) max_episode_step = ( envs.env_fns[0]().spec.max_episode_steps diff --git a/tests/wrappers/test_video_recorder.py b/tests/wrappers/test_video_recorder.py index 863b3a5bc..2c6a6597d 100644 --- a/tests/wrappers/test_video_recorder.py +++ b/tests/wrappers/test_video_recorder.py @@ -2,6 +2,8 @@ import os import time +import pytest + import gym from gym.wrappers.monitoring.video_recorder import VideoRecorder @@ -82,6 +84,7 @@ def test_record_unrecordable_method(): rec.close() +@pytest.mark.filterwarnings("ignore:.*Env returned None on render.*") def test_record_breaking_render_method(): env = BrokenRecordableEnv() rec = VideoRecorder(env)