We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[Bug Report] Undue UserWarning: We recommend you to use a symmetric and normalized Box action space (range=[-1, 1])
It seems like there is an inversion in the `gym.utils.env_checker.check_env` function: observation space is checked with `check_action_space`

https://github.com/openai/gym/blob/053ee809324861dc1bec19feee97b47ba1557a94/gym/utils/env_checker.py#L237

and action space is checked with `check_observation_space`

https://github.com/openai/gym/blob/053ee809324861dc1bec19feee97b47ba1557a94/gym/utils/env_checker.py#L233

causing undue warnings such as 

```log
UserWarning: WARN: We recommend you to use a symmetric and normalized Box action space (range=[-1, 1])
```

### Checklist

- [x] I have checked that there is no similar [issue](https://github.com/openai/gym/issues) in the repo (**required**)


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `gym/wrappers/env_checker.py`
Content:
```
1 """A passive environment checker wrapper for an environment's observation and action space along with the reset, step and render functions."""
2 from typing import Tuple, Union
3 
4 import gym
5 from gym.core import ActType, ObsType
6 from gym.utils.passive_env_checker import (
7     check_action_space,
8     check_observation_space,
9     passive_env_render_check,
10     passive_env_reset_check,
11     passive_env_step_check,
12 )
13 
14 
15 class PassiveEnvChecker(gym.Wrapper):
16     """A passive environment checker wrapper that surrounds the step, reset and render functions to check they follow the gym API."""
17 
18     def __init__(self, env):
19         """Initialises the wrapper with the environments, run the observation and action space tests."""
20         super().__init__(env)
21 
22         assert hasattr(
23             env, "action_space"
24         ), "You must specify a action space. https://www.gymlibrary.ml/content/environment_creation/"
25         check_observation_space(env.action_space)
26         assert hasattr(
27             env, "observation_space"
28         ), "You must specify an observation space. https://www.gymlibrary.ml/content/environment_creation/"
29         check_action_space(env.observation_space)
30 
31         self.checked_reset = False
32         self.checked_step = False
33         self.checked_render = False
34 
35     def step(self, action: ActType) -> Tuple[ObsType, float, bool, dict]:
36         """Steps through the environment that on the first call will run the `passive_env_step_check`."""
37         if self.checked_step is False:
38             self.checked_step = True
39             return passive_env_step_check(self.env, action)
40         else:
41             return self.env.step(action)
42 
43     def reset(self, **kwargs) -> Union[ObsType, Tuple[ObsType, dict]]:
44         """Resets the environment that on the first call will run the `passive_env_reset_check`."""
45         if self.checked_reset is False:
46             self.checked_reset = True
47             return passive_env_reset_check(self.env, **kwargs)
48         else:
49             return self.env.reset(**kwargs)
50 
51     def render(self, *args, **kwargs):
52         """Renders the environment that on the first call will run the `passive_env_render_check`."""
53         if self.checked_render is False:
54             self.checked_render = True
55             return passive_env_render_check(self.env, *args, **kwargs)
56         else:
57             return self.env.render(*args, **kwargs)
58
```

Path: `gym/utils/env_checker.py`
Content:
```
1 """A set of functions for checking an environment details.
2 
3 This file is originally from the Stable Baselines3 repository hosted on GitHub
4 (https://github.com/DLR-RM/stable-baselines3/)
5 Original Author: Antonin Raffin
6 
7 It also uses some warnings/assertions from the PettingZoo repository hosted on GitHub
8 (https://github.com/PettingZoo-Team/PettingZoo)
9 Original Author: J K Terry
10 
11 This was rewritten and split into "env_checker.py" and "passive_env_checker.py" for invasive and passive environment checking
12 Original Author: Mark Towers
13 
14 These projects are covered by the MIT License.
15 """
16 
17 import inspect
18 from copy import deepcopy
19 
20 import numpy as np
21 
22 import gym
23 from gym import error, logger
24 from gym.utils.passive_env_checker import (
25     check_action_space,
26     check_observation_space,
27     passive_env_reset_check,
28     passive_env_step_check,
29 )
30 
31 
32 def data_equivalence(data_1, data_2) -> bool:
33     """Assert equality between data 1 and 2, i.e observations, actions, info.
34 
35     Args:
36         data_1: data structure 1
37         data_2: data structure 2
38 
39     Returns:
40         If observation 1 and 2 are equivalent
41     """
42     if type(data_1) == type(data_2):
43         if isinstance(data_1, dict):
44             return data_1.keys() == data_2.keys() and all(
45                 data_equivalence(data_1[k], data_2[k]) for k in data_1.keys()
46             )
47         elif isinstance(data_1, tuple):
48             return len(data_1) == len(data_2) and all(
49                 data_equivalence(o_1, o_2) for o_1, o_2 in zip(data_1, data_2)
50             )
51         elif isinstance(data_1, np.ndarray):
52             return np.all(data_1 == data_2)
53         else:
54             return data_1 == data_2
55     else:
56         return False
57 
58 
59 def check_reset_seed(env: gym.Env):
60     """Check that the environment can be reset with a seed.
61 
62     Args:
63         env: The environment to check
64 
65     Raises:
66         AssertionError: The environment cannot be reset with a random seed,
67             even though `seed` or `kwargs` appear in the signature.
68     """
69     signature = inspect.signature(env.reset)
70     if "seed" in signature.parameters or "kwargs" in signature.parameters:
71         try:
72             obs_1 = env.reset(seed=123)
73             assert obs_1 in env.observation_space
74             obs_2 = env.reset(seed=123)
75             assert obs_2 in env.observation_space
76             assert data_equivalence(obs_1, obs_2)
77             seed_123_rng = deepcopy(env.unwrapped.np_random)
78 
79             # Note: for some environment, they may initialise at the same state, therefore we cannot check the obs_1 != obs_3
80             obs_4 = env.reset(seed=None)
81             assert obs_4 in env.observation_space
82 
83             assert (
84                 env.unwrapped.np_random.bit_generator.state
85                 != seed_123_rng.bit_generator.state
86             )
87         except TypeError as e:
88             raise AssertionError(
89                 "The environment cannot be reset with a random seed, even though `seed` or `kwargs` appear in the signature. "
90                 "This should never happen, please report this issue. "
91                 f"The error was: {e}"
92             )
93 
94         if env.unwrapped.np_random is None:
95             logger.warn(
96                 "Resetting the environment did not result in seeding its random number generator. "
97                 "This is likely due to not calling `super().reset(seed=seed)` in the `reset` method. "
98                 "If you do not use the python-level random number generator, this is not a problem."
99             )
100 
101         seed_param = signature.parameters.get("seed")
102         # Check the default value is None
103         if seed_param is not None and seed_param.default is not None:
104             logger.warn(
105                 "The default seed argument in reset should be `None`, "
106                 "otherwise the environment will by default always be deterministic"
107             )
108     else:
109         raise error.Error(
110             "The `reset` method does not provide the `return_info` keyword argument"
111         )
112 
113 
114 def check_reset_info(env: gym.Env):
115     """Checks that :meth:`reset` supports the ``return_info`` keyword.
116 
117     Args:
118         env: The environment to check
119 
120     Raises:
121         AssertionError: The environment cannot be reset with `return_info=True`,
122             even though `return_info` or `kwargs` appear in the signature.
123     """
124     signature = inspect.signature(env.reset)
125     if "return_info" in signature.parameters or "kwargs" in signature.parameters:
126         try:
127             result = env.reset(return_info=True)
128             assert (
129                 len(result) == 2
130             ), "Calling the reset method with `return_info=True` did not return a 2-tuple"
131             obs, info = result
132             assert isinstance(
133                 info, dict
134             ), "The second element returned by `env.reset(return_info=True)` was not a dictionary"
135         except TypeError as e:
136             raise AssertionError(
137                 "The environment cannot be reset with `return_info=True`, even though `return_info` or `kwargs` "
138                 "appear in the signature. This should never happen, please report this issue. "
139                 f"The error was: {e}"
140             )
141     else:
142         raise error.Error(
143             "The `reset` method does not provide the `return_info` keyword argument"
144         )
145 
146 
147 def check_reset_options(env: gym.Env):
148     """Check that the environment can be reset with options.
149 
150     Args:
151         env: The environment to check
152 
153     Raises:
154         AssertionError: The environment cannot be reset with options,
155             even though `options` or `kwargs` appear in the signature.
156     """
157     signature = inspect.signature(env.reset)
158     if "options" in signature.parameters or "kwargs" in signature.parameters:
159         try:
160             env.reset(options={})
161         except TypeError as e:
162             raise AssertionError(
163                 "The environment cannot be reset with options, even though `options` or `kwargs` appear in the signature. "
164                 "This should never happen, please report this issue. "
165                 f"The error was: {e}"
166             )
167     else:
168         raise error.Error(
169             "The `reset` method does not provide the `options` keyword argument"
170         )
171 
172 
173 def check_render(env: gym.Env, warn: bool = True):
174     """Check the declared render modes/fps of the environment.
175 
176     Args:
177         env: The environment to check
178         warn: Whether to output additional warnings
179     """
180     render_modes = env.metadata.get("render_modes")
181     if render_modes is None:
182         if warn:
183             logger.warn(
184                 "No render modes was declared in the environment "
185                 " (env.metadata['render_modes'] is None or not defined), "
186                 "you may have trouble when calling `.render()`"
187             )
188 
189     render_fps = env.metadata.get("render_fps")
190     # We only require `render_fps` if rendering is actually implemented
191     if render_fps is None and render_modes is not None and len(render_modes) > 0:
192         if warn:
193             logger.warn(
194                 "No render fps was declared in the environment "
195                 " (env.metadata['render_fps'] is None or not defined), "
196                 "rendering may occur at inconsistent fps"
197             )
198 
199     if warn:
200         if not hasattr(env, "render_mode"):  # TODO: raise an error with gym 1.0
201             logger.warn("Environments must define render_mode attribute.")
202         elif env.render_mode is not None and env.render_mode not in render_modes:
203             logger.warn(
204                 "The environment was initialized successfully with an unsupported render mode."
205             )
206 
207 
208 def check_env(env: gym.Env, warn: bool = None, skip_render_check: bool = True):
209     """Check that an environment follows Gym API.
210 
211     This is an invasive function that calls the environment's reset and step.
212 
213     This is particularly useful when using a custom environment.
214     Please take a look at https://www.gymlibrary.ml/content/environment_creation/
215     for more information about the API.
216 
217     Args:
218         env: The Gym environment that will be checked
219         warn: Ignored
220         skip_render_check: Whether to skip the checks for the render method. True by default (useful for the CI)
221     """
222     if warn is not None:
223         logger.warn("`check_env` warn parameter is now ignored.")
224 
225     assert isinstance(
226         env, gym.Env
227     ), "Your environment must inherit from the gym.Env class https://www.gymlibrary.ml/content/environment_creation/"
228 
229     # ============= Check the spaces (observation and action) ================
230     assert hasattr(
231         env, "action_space"
232     ), "You must specify a action space. https://www.gymlibrary.ml/content/environment_creation/"
233     check_observation_space(env.action_space)
234     assert hasattr(
235         env, "observation_space"
236     ), "You must specify an observation space. https://www.gymlibrary.ml/content/environment_creation/"
237     check_action_space(env.observation_space)
238 
239     # ==== Check the reset method ====
240     check_reset_seed(env)
241     check_reset_options(env)
242     check_reset_info(env)
243 
244     # ============ Check the returned values ===============
245     passive_env_reset_check(env)
246     passive_env_step_check(env, env.action_space.sample())
247 
248     # ==== Check the render method and the declared render modes ====
249     if not skip_render_check:
250         check_render(env)
251
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/gym/utils/env_checker.py b/gym/utils/env_checker.py
--- a/gym/utils/env_checker.py
+++ b/gym/utils/env_checker.py
@@ -230,11 +230,11 @@
     assert hasattr(
         env, "action_space"
     ), "You must specify a action space. https://www.gymlibrary.ml/content/environment_creation/"
-    check_observation_space(env.action_space)
+    check_action_space(env.action_space)
     assert hasattr(
         env, "observation_space"
     ), "You must specify an observation space. https://www.gymlibrary.ml/content/environment_creation/"
-    check_action_space(env.observation_space)
+    check_observation_space(env.observation_space)
 
     # ==== Check the reset method ====
     check_reset_seed(env)
diff --git a/gym/wrappers/env_checker.py b/gym/wrappers/env_checker.py
--- a/gym/wrappers/env_checker.py
+++ b/gym/wrappers/env_checker.py
@@ -22,11 +22,11 @@
         assert hasattr(
             env, "action_space"
         ), "You must specify a action space. https://www.gymlibrary.ml/content/environment_creation/"
-        check_observation_space(env.action_space)
+        check_action_space(env.action_space)
         assert hasattr(
             env, "observation_space"
         ), "You must specify an observation space. https://www.gymlibrary.ml/content/environment_creation/"
-        check_action_space(env.observation_space)
+        check_observation_space(env.observation_space)
 
         self.checked_reset = False
         self.checked_step = False

{"golden_diff": "diff --git a/gym/utils/env_checker.py b/gym/utils/env_checker.py\n--- a/gym/utils/env_checker.py\n+++ b/gym/utils/env_checker.py\n@@ -230,11 +230,11 @@\n     assert hasattr(\n         env, \"action_space\"\n     ), \"You must specify a action space. https://www.gymlibrary.ml/content/environment_creation/\"\n-    check_observation_space(env.action_space)\n+    check_action_space(env.action_space)\n     assert hasattr(\n         env, \"observation_space\"\n     ), \"You must specify an observation space. https://www.gymlibrary.ml/content/environment_creation/\"\n-    check_action_space(env.observation_space)\n+    check_observation_space(env.observation_space)\n \n     # ==== Check the reset method ====\n     check_reset_seed(env)\ndiff --git a/gym/wrappers/env_checker.py b/gym/wrappers/env_checker.py\n--- a/gym/wrappers/env_checker.py\n+++ b/gym/wrappers/env_checker.py\n@@ -22,11 +22,11 @@\n         assert hasattr(\n             env, \"action_space\"\n         ), \"You must specify a action space. https://www.gymlibrary.ml/content/environment_creation/\"\n-        check_observation_space(env.action_space)\n+        check_action_space(env.action_space)\n         assert hasattr(\n             env, \"observation_space\"\n         ), \"You must specify an observation space. https://www.gymlibrary.ml/content/environment_creation/\"\n-        check_action_space(env.observation_space)\n+        check_observation_space(env.observation_space)\n \n         self.checked_reset = False\n         self.checked_step = False\n", "issue": "[Bug Report] Undue UserWarning: We recommend you to use a symmetric and normalized Box action space (range=[-1, 1])\nIt seems like there is an inversion in the `gym.utils.env_checker.check_env` function: observation space is checked with `check_action_space`\r\n\r\nhttps://github.com/openai/gym/blob/053ee809324861dc1bec19feee97b47ba1557a94/gym/utils/env_checker.py#L237\r\n\r\nand action space is checked with `check_observation_space`\r\n\r\nhttps://github.com/openai/gym/blob/053ee809324861dc1bec19feee97b47ba1557a94/gym/utils/env_checker.py#L233\r\n\r\ncausing undue warnings such as \r\n\r\n```log\r\nUserWarning: WARN: We recommend you to use a symmetric and normalized Box action space (range=[-1, 1])\r\n```\r\n\r\n### Checklist\r\n\r\n- [x] I have checked that there is no similar [issue](https://github.com/openai/gym/issues) in the repo (**required**)\r\n\n", "before_files": [{"content": "\"\"\"A passive environment checker wrapper for an environment's observation and action space along with the reset, step and render functions.\"\"\"\nfrom typing import Tuple, Union\n\nimport gym\nfrom gym.core import ActType, ObsType\nfrom gym.utils.passive_env_checker import (\n    check_action_space,\n    check_observation_space,\n    passive_env_render_check,\n    passive_env_reset_check,\n    passive_env_step_check,\n)\n\n\nclass PassiveEnvChecker(gym.Wrapper):\n    \"\"\"A passive environment checker wrapper that surrounds the step, reset and render functions to check they follow the gym API.\"\"\"\n\n    def __init__(self, env):\n        \"\"\"Initialises the wrapper with the environments, run the observation and action space tests.\"\"\"\n        super().__init__(env)\n\n        assert hasattr(\n            env, \"action_space\"\n        ), \"You must specify a action space. https://www.gymlibrary.ml/content/environment_creation/\"\n        check_observation_space(env.action_space)\n        assert hasattr(\n            env, \"observation_space\"\n        ), \"You must specify an observation space. https://www.gymlibrary.ml/content/environment_creation/\"\n        check_action_space(env.observation_space)\n\n        self.checked_reset = False\n        self.checked_step = False\n        self.checked_render = False\n\n    def step(self, action: ActType) -> Tuple[ObsType, float, bool, dict]:\n        \"\"\"Steps through the environment that on the first call will run the `passive_env_step_check`.\"\"\"\n        if self.checked_step is False:\n            self.checked_step = True\n            return passive_env_step_check(self.env, action)\n        else:\n            return self.env.step(action)\n\n    def reset(self, **kwargs) -> Union[ObsType, Tuple[ObsType, dict]]:\n        \"\"\"Resets the environment that on the first call will run the `passive_env_reset_check`.\"\"\"\n        if self.checked_reset is False:\n            self.checked_reset = True\n            return passive_env_reset_check(self.env, **kwargs)\n        else:\n            return self.env.reset(**kwargs)\n\n    def render(self, *args, **kwargs):\n        \"\"\"Renders the environment that on the first call will run the `passive_env_render_check`.\"\"\"\n        if self.checked_render is False:\n            self.checked_render = True\n            return passive_env_render_check(self.env, *args, **kwargs)\n        else:\n            return self.env.render(*args, **kwargs)\n", "path": "gym/wrappers/env_checker.py"}, {"content": "\"\"\"A set of functions for checking an environment details.\n\nThis file is originally from the Stable Baselines3 repository hosted on GitHub\n(https://github.com/DLR-RM/stable-baselines3/)\nOriginal Author: Antonin Raffin\n\nIt also uses some warnings/assertions from the PettingZoo repository hosted on GitHub\n(https://github.com/PettingZoo-Team/PettingZoo)\nOriginal Author: J K Terry\n\nThis was rewritten and split into \"env_checker.py\" and \"passive_env_checker.py\" for invasive and passive environment checking\nOriginal Author: Mark Towers\n\nThese projects are covered by the MIT License.\n\"\"\"\n\nimport inspect\nfrom copy import deepcopy\n\nimport numpy as np\n\nimport gym\nfrom gym import error, logger\nfrom gym.utils.passive_env_checker import (\n    check_action_space,\n    check_observation_space,\n    passive_env_reset_check,\n    passive_env_step_check,\n)\n\n\ndef data_equivalence(data_1, data_2) -> bool:\n    \"\"\"Assert equality between data 1 and 2, i.e observations, actions, info.\n\n    Args:\n        data_1: data structure 1\n        data_2: data structure 2\n\n    Returns:\n        If observation 1 and 2 are equivalent\n    \"\"\"\n    if type(data_1) == type(data_2):\n        if isinstance(data_1, dict):\n            return data_1.keys() == data_2.keys() and all(\n                data_equivalence(data_1[k], data_2[k]) for k in data_1.keys()\n            )\n        elif isinstance(data_1, tuple):\n            return len(data_1) == len(data_2) and all(\n                data_equivalence(o_1, o_2) for o_1, o_2 in zip(data_1, data_2)\n            )\n        elif isinstance(data_1, np.ndarray):\n            return np.all(data_1 == data_2)\n        else:\n            return data_1 == data_2\n    else:\n        return False\n\n\ndef check_reset_seed(env: gym.Env):\n    \"\"\"Check that the environment can be reset with a seed.\n\n    Args:\n        env: The environment to check\n\n    Raises:\n        AssertionError: The environment cannot be reset with a random seed,\n            even though `seed` or `kwargs` appear in the signature.\n    \"\"\"\n    signature = inspect.signature(env.reset)\n    if \"seed\" in signature.parameters or \"kwargs\" in signature.parameters:\n        try:\n            obs_1 = env.reset(seed=123)\n            assert obs_1 in env.observation_space\n            obs_2 = env.reset(seed=123)\n            assert obs_2 in env.observation_space\n            assert data_equivalence(obs_1, obs_2)\n            seed_123_rng = deepcopy(env.unwrapped.np_random)\n\n            # Note: for some environment, they may initialise at the same state, therefore we cannot check the obs_1 != obs_3\n            obs_4 = env.reset(seed=None)\n            assert obs_4 in env.observation_space\n\n            assert (\n                env.unwrapped.np_random.bit_generator.state\n                != seed_123_rng.bit_generator.state\n            )\n        except TypeError as e:\n            raise AssertionError(\n                \"The environment cannot be reset with a random seed, even though `seed` or `kwargs` appear in the signature. \"\n                \"This should never happen, please report this issue. \"\n                f\"The error was: {e}\"\n            )\n\n        if env.unwrapped.np_random is None:\n            logger.warn(\n                \"Resetting the environment did not result in seeding its random number generator. \"\n                \"This is likely due to not calling `super().reset(seed=seed)` in the `reset` method. \"\n                \"If you do not use the python-level random number generator, this is not a problem.\"\n            )\n\n        seed_param = signature.parameters.get(\"seed\")\n        # Check the default value is None\n        if seed_param is not None and seed_param.default is not None:\n            logger.warn(\n                \"The default seed argument in reset should be `None`, \"\n                \"otherwise the environment will by default always be deterministic\"\n            )\n    else:\n        raise error.Error(\n            \"The `reset` method does not provide the `return_info` keyword argument\"\n        )\n\n\ndef check_reset_info(env: gym.Env):\n    \"\"\"Checks that :meth:`reset` supports the ``return_info`` keyword.\n\n    Args:\n        env: The environment to check\n\n    Raises:\n        AssertionError: The environment cannot be reset with `return_info=True`,\n            even though `return_info` or `kwargs` appear in the signature.\n    \"\"\"\n    signature = inspect.signature(env.reset)\n    if \"return_info\" in signature.parameters or \"kwargs\" in signature.parameters:\n        try:\n            result = env.reset(return_info=True)\n            assert (\n                len(result) == 2\n            ), \"Calling the reset method with `return_info=True` did not return a 2-tuple\"\n            obs, info = result\n            assert isinstance(\n                info, dict\n            ), \"The second element returned by `env.reset(return_info=True)` was not a dictionary\"\n        except TypeError as e:\n            raise AssertionError(\n                \"The environment cannot be reset with `return_info=True`, even though `return_info` or `kwargs` \"\n                \"appear in the signature. This should never happen, please report this issue. \"\n                f\"The error was: {e}\"\n            )\n    else:\n        raise error.Error(\n            \"The `reset` method does not provide the `return_info` keyword argument\"\n        )\n\n\ndef check_reset_options(env: gym.Env):\n    \"\"\"Check that the environment can be reset with options.\n\n    Args:\n        env: The environment to check\n\n    Raises:\n        AssertionError: The environment cannot be reset with options,\n            even though `options` or `kwargs` appear in the signature.\n    \"\"\"\n    signature = inspect.signature(env.reset)\n    if \"options\" in signature.parameters or \"kwargs\" in signature.parameters:\n        try:\n            env.reset(options={})\n        except TypeError as e:\n            raise AssertionError(\n                \"The environment cannot be reset with options, even though `options` or `kwargs` appear in the signature. \"\n                \"This should never happen, please report this issue. \"\n                f\"The error was: {e}\"\n            )\n    else:\n        raise error.Error(\n            \"The `reset` method does not provide the `options` keyword argument\"\n        )\n\n\ndef check_render(env: gym.Env, warn: bool = True):\n    \"\"\"Check the declared render modes/fps of the environment.\n\n    Args:\n        env: The environment to check\n        warn: Whether to output additional warnings\n    \"\"\"\n    render_modes = env.metadata.get(\"render_modes\")\n    if render_modes is None:\n        if warn:\n            logger.warn(\n                \"No render modes was declared in the environment \"\n                \" (env.metadata['render_modes'] is None or not defined), \"\n                \"you may have trouble when calling `.render()`\"\n            )\n\n    render_fps = env.metadata.get(\"render_fps\")\n    # We only require `render_fps` if rendering is actually implemented\n    if render_fps is None and render_modes is not None and len(render_modes) > 0:\n        if warn:\n            logger.warn(\n                \"No render fps was declared in the environment \"\n                \" (env.metadata['render_fps'] is None or not defined), \"\n                \"rendering may occur at inconsistent fps\"\n            )\n\n    if warn:\n        if not hasattr(env, \"render_mode\"):  # TODO: raise an error with gym 1.0\n            logger.warn(\"Environments must define render_mode attribute.\")\n        elif env.render_mode is not None and env.render_mode not in render_modes:\n            logger.warn(\n                \"The environment was initialized successfully with an unsupported render mode.\"\n            )\n\n\ndef check_env(env: gym.Env, warn: bool = None, skip_render_check: bool = True):\n    \"\"\"Check that an environment follows Gym API.\n\n    This is an invasive function that calls the environment's reset and step.\n\n    This is particularly useful when using a custom environment.\n    Please take a look at https://www.gymlibrary.ml/content/environment_creation/\n    for more information about the API.\n\n    Args:\n        env: The Gym environment that will be checked\n        warn: Ignored\n        skip_render_check: Whether to skip the checks for the render method. True by default (useful for the CI)\n    \"\"\"\n    if warn is not None:\n        logger.warn(\"`check_env` warn parameter is now ignored.\")\n\n    assert isinstance(\n        env, gym.Env\n    ), \"Your environment must inherit from the gym.Env class https://www.gymlibrary.ml/content/environment_creation/\"\n\n    # ============= Check the spaces (observation and action) ================\n    assert hasattr(\n        env, \"action_space\"\n    ), \"You must specify a action space. https://www.gymlibrary.ml/content/environment_creation/\"\n    check_observation_space(env.action_space)\n    assert hasattr(\n        env, \"observation_space\"\n    ), \"You must specify an observation space. https://www.gymlibrary.ml/content/environment_creation/\"\n    check_action_space(env.observation_space)\n\n    # ==== Check the reset method ====\n    check_reset_seed(env)\n    check_reset_options(env)\n    check_reset_info(env)\n\n    # ============ Check the returned values ===============\n    passive_env_reset_check(env)\n    passive_env_step_check(env, env.action_space.sample())\n\n    # ==== Check the render method and the declared render modes ====\n    if not skip_render_check:\n        check_render(env)\n", "path": "gym/utils/env_checker.py"}], "after_files": [{"content": "\"\"\"A passive environment checker wrapper for an environment's observation and action space along with the reset, step and render functions.\"\"\"\nfrom typing import Tuple, Union\n\nimport gym\nfrom gym.core import ActType, ObsType\nfrom gym.utils.passive_env_checker import (\n    check_action_space,\n    check_observation_space,\n    passive_env_render_check,\n    passive_env_reset_check,\n    passive_env_step_check,\n)\n\n\nclass PassiveEnvChecker(gym.Wrapper):\n    \"\"\"A passive environment checker wrapper that surrounds the step, reset and render functions to check they follow the gym API.\"\"\"\n\n    def __init__(self, env):\n        \"\"\"Initialises the wrapper with the environments, run the observation and action space tests.\"\"\"\n        super().__init__(env)\n\n        assert hasattr(\n            env, \"action_space\"\n        ), \"You must specify a action space. https://www.gymlibrary.ml/content/environment_creation/\"\n        check_action_space(env.action_space)\n        assert hasattr(\n            env, \"observation_space\"\n        ), \"You must specify an observation space. https://www.gymlibrary.ml/content/environment_creation/\"\n        check_observation_space(env.observation_space)\n\n        self.checked_reset = False\n        self.checked_step = False\n        self.checked_render = False\n\n    def step(self, action: ActType) -> Tuple[ObsType, float, bool, dict]:\n        \"\"\"Steps through the environment that on the first call will run the `passive_env_step_check`.\"\"\"\n        if self.checked_step is False:\n            self.checked_step = True\n            return passive_env_step_check(self.env, action)\n        else:\n            return self.env.step(action)\n\n    def reset(self, **kwargs) -> Union[ObsType, Tuple[ObsType, dict]]:\n        \"\"\"Resets the environment that on the first call will run the `passive_env_reset_check`.\"\"\"\n        if self.checked_reset is False:\n            self.checked_reset = True\n            return passive_env_reset_check(self.env, **kwargs)\n        else:\n            return self.env.reset(**kwargs)\n\n    def render(self, *args, **kwargs):\n        \"\"\"Renders the environment that on the first call will run the `passive_env_render_check`.\"\"\"\n        if self.checked_render is False:\n            self.checked_render = True\n            return passive_env_render_check(self.env, *args, **kwargs)\n        else:\n            return self.env.render(*args, **kwargs)\n", "path": "gym/wrappers/env_checker.py"}, {"content": "\"\"\"A set of functions for checking an environment details.\n\nThis file is originally from the Stable Baselines3 repository hosted on GitHub\n(https://github.com/DLR-RM/stable-baselines3/)\nOriginal Author: Antonin Raffin\n\nIt also uses some warnings/assertions from the PettingZoo repository hosted on GitHub\n(https://github.com/PettingZoo-Team/PettingZoo)\nOriginal Author: J K Terry\n\nThis was rewritten and split into \"env_checker.py\" and \"passive_env_checker.py\" for invasive and passive environment checking\nOriginal Author: Mark Towers\n\nThese projects are covered by the MIT License.\n\"\"\"\n\nimport inspect\nfrom copy import deepcopy\n\nimport numpy as np\n\nimport gym\nfrom gym import error, logger\nfrom gym.utils.passive_env_checker import (\n    check_action_space,\n    check_observation_space,\n    passive_env_reset_check,\n    passive_env_step_check,\n)\n\n\ndef data_equivalence(data_1, data_2) -> bool:\n    \"\"\"Assert equality between data 1 and 2, i.e observations, actions, info.\n\n    Args:\n        data_1: data structure 1\n        data_2: data structure 2\n\n    Returns:\n        If observation 1 and 2 are equivalent\n    \"\"\"\n    if type(data_1) == type(data_2):\n        if isinstance(data_1, dict):\n            return data_1.keys() == data_2.keys() and all(\n                data_equivalence(data_1[k], data_2[k]) for k in data_1.keys()\n            )\n        elif isinstance(data_1, tuple):\n            return len(data_1) == len(data_2) and all(\n                data_equivalence(o_1, o_2) for o_1, o_2 in zip(data_1, data_2)\n            )\n        elif isinstance(data_1, np.ndarray):\n            return np.all(data_1 == data_2)\n        else:\n            return data_1 == data_2\n    else:\n        return False\n\n\ndef check_reset_seed(env: gym.Env):\n    \"\"\"Check that the environment can be reset with a seed.\n\n    Args:\n        env: The environment to check\n\n    Raises:\n        AssertionError: The environment cannot be reset with a random seed,\n            even though `seed` or `kwargs` appear in the signature.\n    \"\"\"\n    signature = inspect.signature(env.reset)\n    if \"seed\" in signature.parameters or \"kwargs\" in signature.parameters:\n        try:\n            obs_1 = env.reset(seed=123)\n            assert obs_1 in env.observation_space\n            obs_2 = env.reset(seed=123)\n            assert obs_2 in env.observation_space\n            assert data_equivalence(obs_1, obs_2)\n            seed_123_rng = deepcopy(env.unwrapped.np_random)\n\n            # Note: for some environment, they may initialise at the same state, therefore we cannot check the obs_1 != obs_3\n            obs_4 = env.reset(seed=None)\n            assert obs_4 in env.observation_space\n\n            assert (\n                env.unwrapped.np_random.bit_generator.state\n                != seed_123_rng.bit_generator.state\n            )\n        except TypeError as e:\n            raise AssertionError(\n                \"The environment cannot be reset with a random seed, even though `seed` or `kwargs` appear in the signature. \"\n                \"This should never happen, please report this issue. \"\n                f\"The error was: {e}\"\n            )\n\n        if env.unwrapped.np_random is None:\n            logger.warn(\n                \"Resetting the environment did not result in seeding its random number generator. \"\n                \"This is likely due to not calling `super().reset(seed=seed)` in the `reset` method. \"\n                \"If you do not use the python-level random number generator, this is not a problem.\"\n            )\n\n        seed_param = signature.parameters.get(\"seed\")\n        # Check the default value is None\n        if seed_param is not None and seed_param.default is not None:\n            logger.warn(\n                \"The default seed argument in reset should be `None`, \"\n                \"otherwise the environment will by default always be deterministic\"\n            )\n    else:\n        raise error.Error(\n            \"The `reset` method does not provide the `return_info` keyword argument\"\n        )\n\n\ndef check_reset_info(env: gym.Env):\n    \"\"\"Checks that :meth:`reset` supports the ``return_info`` keyword.\n\n    Args:\n        env: The environment to check\n\n    Raises:\n        AssertionError: The environment cannot be reset with `return_info=True`,\n            even though `return_info` or `kwargs` appear in the signature.\n    \"\"\"\n    signature = inspect.signature(env.reset)\n    if \"return_info\" in signature.parameters or \"kwargs\" in signature.parameters:\n        try:\n            result = env.reset(return_info=True)\n            assert (\n                len(result) == 2\n            ), \"Calling the reset method with `return_info=True` did not return a 2-tuple\"\n            obs, info = result\n            assert isinstance(\n                info, dict\n            ), \"The second element returned by `env.reset(return_info=True)` was not a dictionary\"\n        except TypeError as e:\n            raise AssertionError(\n                \"The environment cannot be reset with `return_info=True`, even though `return_info` or `kwargs` \"\n                \"appear in the signature. This should never happen, please report this issue. \"\n                f\"The error was: {e}\"\n            )\n    else:\n        raise error.Error(\n            \"The `reset` method does not provide the `return_info` keyword argument\"\n        )\n\n\ndef check_reset_options(env: gym.Env):\n    \"\"\"Check that the environment can be reset with options.\n\n    Args:\n        env: The environment to check\n\n    Raises:\n        AssertionError: The environment cannot be reset with options,\n            even though `options` or `kwargs` appear in the signature.\n    \"\"\"\n    signature = inspect.signature(env.reset)\n    if \"options\" in signature.parameters or \"kwargs\" in signature.parameters:\n        try:\n            env.reset(options={})\n        except TypeError as e:\n            raise AssertionError(\n                \"The environment cannot be reset with options, even though `options` or `kwargs` appear in the signature. \"\n                \"This should never happen, please report this issue. \"\n                f\"The error was: {e}\"\n            )\n    else:\n        raise error.Error(\n            \"The `reset` method does not provide the `options` keyword argument\"\n        )\n\n\ndef check_render(env: gym.Env, warn: bool = True):\n    \"\"\"Check the declared render modes/fps of the environment.\n\n    Args:\n        env: The environment to check\n        warn: Whether to output additional warnings\n    \"\"\"\n    render_modes = env.metadata.get(\"render_modes\")\n    if render_modes is None:\n        if warn:\n            logger.warn(\n                \"No render modes was declared in the environment \"\n                \" (env.metadata['render_modes'] is None or not defined), \"\n                \"you may have trouble when calling `.render()`\"\n            )\n\n    render_fps = env.metadata.get(\"render_fps\")\n    # We only require `render_fps` if rendering is actually implemented\n    if render_fps is None and render_modes is not None and len(render_modes) > 0:\n        if warn:\n            logger.warn(\n                \"No render fps was declared in the environment \"\n                \" (env.metadata['render_fps'] is None or not defined), \"\n                \"rendering may occur at inconsistent fps\"\n            )\n\n    if warn:\n        if not hasattr(env, \"render_mode\"):  # TODO: raise an error with gym 1.0\n            logger.warn(\"Environments must define render_mode attribute.\")\n        elif env.render_mode is not None and env.render_mode not in render_modes:\n            logger.warn(\n                \"The environment was initialized successfully with an unsupported render mode.\"\n            )\n\n\ndef check_env(env: gym.Env, warn: bool = None, skip_render_check: bool = True):\n    \"\"\"Check that an environment follows Gym API.\n\n    This is an invasive function that calls the environment's reset and step.\n\n    This is particularly useful when using a custom environment.\n    Please take a look at https://www.gymlibrary.ml/content/environment_creation/\n    for more information about the API.\n\n    Args:\n        env: The Gym environment that will be checked\n        warn: Ignored\n        skip_render_check: Whether to skip the checks for the render method. True by default (useful for the CI)\n    \"\"\"\n    if warn is not None:\n        logger.warn(\"`check_env` warn parameter is now ignored.\")\n\n    assert isinstance(\n        env, gym.Env\n    ), \"Your environment must inherit from the gym.Env class https://www.gymlibrary.ml/content/environment_creation/\"\n\n    # ============= Check the spaces (observation and action) ================\n    assert hasattr(\n        env, \"action_space\"\n    ), \"You must specify a action space. https://www.gymlibrary.ml/content/environment_creation/\"\n    check_action_space(env.action_space)\n    assert hasattr(\n        env, \"observation_space\"\n    ), \"You must specify an observation space. https://www.gymlibrary.ml/content/environment_creation/\"\n    check_observation_space(env.observation_space)\n\n    # ==== Check the reset method ====\n    check_reset_seed(env)\n    check_reset_options(env)\n    check_reset_info(env)\n\n    # ============ Check the returned values ===============\n    passive_env_reset_check(env)\n    passive_env_step_check(env, env.action_space.sample())\n\n    # ==== Check the render method and the declared render modes ====\n    if not skip_render_check:\n        check_render(env)\n", "path": "gym/utils/env_checker.py"}]}