From 850247f888cc4642561488b7c17f8b29873b31bd Mon Sep 17 00:00:00 2001 From: Mark Towers Date: Mon, 14 Mar 2022 14:27:03 +0000 Subject: [PATCH] Reduces warnings produced by pytest from ~1500 to 13 (#2660) * Updated cartpole-v0 to v1 to prevent warning and added pytest.mark.filterwarnings for tests where warnings are unavoidable * Change np.bool to bool as numpy raises a warning and bool is the suggested solution * Seeding randint is deprecated in the future, integers is new solution * Fixed errors thrown when the video recorder is deleted but not closed * spaces.Box expects a floating array, updated all cases where this was not true and modified float32 to float64 as float array default to float64. Otherwise space.Box raises warning that dtype precision (float32) is lower than array precision (float64). * Added pytest.mark.filterwarnings to preventing the raising of an intended warning * Added comment to explain why a warning is raised that can't be prevented without version update to the environment * Added comment to explain why warning is raised * Changed values to float as expected by the box which default to float64 * Removed --forked from pytest as the pytest-forked project is no being maintained and was not raising warnings as expected * When AsyncVectorEnv has shared_memory=True then a ValueError is raised before _state is initialised. Therefore, on the destruction on the env an error is thrown in .close_extra as _state does not exist * Possible fix that was causing an error in test_call_async_vector_env by ensuring that pygame resources are released * Pygame throws an error with ALSA when closed, using a fix from PettingZoo (https://github.com/Farama-Foundation/PettingZoo/blob/master/pettingzoo/__init__.py). We use the dsp audiodriver to prevent this issue * Modification due to running pre-commit locally * Updated cartpole-v0 to v1 to prevent warning and added pytest.mark.filterwarnings for tests where warnings are unavoidable * Change np.bool to bool as numpy raises a warning and bool is the suggested solution * Seeding randint is deprecated in the future, integers is new solution * Fixed errors thrown when the video recorder is deleted but not closed * spaces.Box expects a floating array, updated all cases where this was not true and modified float32 to float64 as float array default to float64. Otherwise space.Box raises warning that dtype precision (float32) is lower than array precision (float64). * Added pytest.mark.filterwarnings to preventing the raising of an intended warning * Added comment to explain why a warning is raised that can't be prevented without version update to the environment * Added comment to explain why warning is raised * Changed values to float as expected by the box which default to float64 * Removed --forked from pytest as the pytest-forked project is no being maintained and was not raising warnings as expected * When AsyncVectorEnv has shared_memory=True then a ValueError is raised before _state is initialised. Therefore, on the destruction on the env an error is thrown in .close_extra as _state does not exist * Possible fix that was causing an error in test_call_async_vector_env by ensuring that pygame resources are released * Pygame throws an error with ALSA when closed, using a fix from PettingZoo (https://github.com/Farama-Foundation/PettingZoo/blob/master/pettingzoo/__init__.py). We use the dsp audiodriver to prevent this issue * Modification due to running pre-commit locally --- .github/workflows/build.yml | 2 +- gym/__init__.py | 11 ++- gym/envs/box2d/car_racing.py | 4 +- gym/envs/classic_control/pendulum.py | 5 +- gym/envs/toy_text/cliffwalking.py | 2 +- gym/spaces/dict.py | 2 +- gym/spaces/discrete.py | 2 +- gym/vector/async_vector_env.py | 2 +- gym/wrappers/record_video.py | 6 ++ tests/envs/test_envs.py | 5 +- tests/envs/test_registration.py | 12 ++- tests/spaces/test_spaces.py | 74 ++++++++++++++----- tests/spaces/test_utils.py | 4 +- tests/vector/test_spaces.py | 10 +-- tests/vector/utils.py | 10 +-- tests/wrappers/test_normalize.py | 2 +- .../test_record_episode_statistics.py | 4 +- tests/wrappers/test_video_recorder.py | 3 + 18 files changed, 114 insertions(+), 46 deletions(-) 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)