1212def _is_numpy_array_space (space : spaces .Space ) -> bool :
1313 """
1414 Returns False if provided space is not representable as a single numpy array
15- (e.g. Dict, Tuple spaces return False)
15+ (e.g. Dict and Tuple spaces return False)
1616 """
1717 return not isinstance (space , (spaces .Dict , spaces .Tuple ))
1818
@@ -80,14 +80,21 @@ def _check_image_input(observation_space: spaces.Box, key: str = "") -> None:
8080 )
8181
8282
83- def _check_unsupported_spaces (env : gym .Env , observation_space : spaces .Space , action_space : spaces .Space ) -> None :
84- """Emit warnings when the observation space or action space used is not supported by Stable-Baselines."""
83+ def _check_unsupported_spaces (env : gym .Env , observation_space : spaces .Space , action_space : spaces .Space ) -> bool :
84+ """
85+ Emit warnings when the observation space or action space used is not supported by Stable-Baselines.
86+
87+ :return: True if return value tests should be skipped.
88+ """
8589
90+ should_skip = graph_space = False
8691 if isinstance (observation_space , spaces .Dict ):
8792 nested_dict = False
8893 for key , space in observation_space .spaces .items ():
8994 if isinstance (space , spaces .Dict ):
9095 nested_dict = True
96+ if isinstance (space , spaces .Graph ):
97+ graph_space = True
9198 _check_non_zero_start (space , "observation" , key )
9299
93100 if nested_dict :
@@ -124,6 +131,14 @@ def _check_unsupported_spaces(env: gym.Env, observation_space: spaces.Space, act
124131 "You can pad your observation to have a fixed size instead.\n "
125132 "Note: The checks for returned values are skipped."
126133 )
134+ should_skip = True
135+
136+ if isinstance (observation_space , spaces .Graph ) or graph_space :
137+ warnings .warn (
138+ "Graph observation space is not supported by Stable-Baselines3. "
139+ "Note: The checks for returned values are skipped."
140+ )
141+ should_skip = True
127142
128143 _check_non_zero_start (action_space , "action" )
129144
@@ -133,6 +148,7 @@ def _check_unsupported_spaces(env: gym.Env, observation_space: spaces.Space, act
133148 "This type of action space is currently not supported by Stable Baselines 3. You should try to flatten the "
134149 "action using a wrapper."
135150 )
151+ return should_skip
136152
137153
138154def _check_nan (env : gym .Env ) -> None :
@@ -204,26 +220,10 @@ def _check_obs(obs: Union[tuple, dict, np.ndarray, int], observation_space: spac
204220 Check that the observation returned by the environment
205221 correspond to the declared one.
206222 """
207- # If the observation space is a Graph, return early with a warning.
208- if _is_graph_space (observation_space ):
209- warnings .warn (
210- f"The observation space for `{ method_name } ()` is a Graph space, which is not supported the env checker." ,
211- "Skipping further observation checks." ,
212- UserWarning ,
213- )
214- return
215-
216223 if not isinstance (observation_space , spaces .Tuple ):
217224 assert not isinstance (
218225 obs , tuple
219226 ), f"The observation returned by the `{ method_name } ()` method should be a single value, not a tuple"
220- # Graph spaces are not fully supported by the env checker
221- if isinstance (observation_space , spaces .Graph ):
222- warnings .warn (
223- "Graph observation spaces are not fully supported by the env checker. "
224- "Skipping further observation checks."
225- )
226- return
227227 # The check for a GoalEnv is done by the base class
228228 if isinstance (observation_space , spaces .Discrete ):
229229 # Since https://github.com/Farama-Foundation/Gymnasium/pull/141,
@@ -371,7 +371,6 @@ def _check_returned_values(env: gym.Env, observation_space: spaces.Space, action
371371 assert reward == env .compute_reward (obs ["achieved_goal" ], obs ["desired_goal" ], info )
372372
373373
374-
375374def _check_spaces (env : gym .Env ) -> None :
376375 """
377376 Check that the observation and action spaces are defined and inherit from spaces.Space. For
@@ -400,18 +399,6 @@ def _check_spaces(env: gym.Env) -> None:
400399 )
401400
402401
403- def _is_graph_space (space : Any ) -> bool :
404- """
405- Check if the space is a gymnasium Graph space.
406- Handles the case where gymnasium.spaces.graph may not be available.
407- """
408- try :
409- from gymnasium .spaces .graph import Graph
410- except ImportError :
411- return False
412- return isinstance (space , Graph )
413-
414-
415402# Check render cannot be covered by CI
416403def _check_render (env : gym .Env , warn : bool = False ) -> None : # pragma: no cover
417404 """
@@ -470,8 +457,10 @@ def check_env(env: gym.Env, warn: bool = True, skip_render_check: bool = True) -
470457 raise TypeError ("The reset() method must accept a `seed` parameter" ) from e
471458
472459 # Warn the user if needed.
460+ # A warning means that the environment may run but not work properly with Stable Baselines algorithms
461+ should_skip = False
473462 if warn :
474- _check_unsupported_spaces (env , observation_space , action_space )
463+ should_skip = _check_unsupported_spaces (env , observation_space , action_space )
475464
476465 obs_spaces = observation_space .spaces if isinstance (observation_space , spaces .Dict ) else {"" : observation_space }
477466 for key , space in obs_spaces .items ():
@@ -499,8 +488,8 @@ def check_env(env: gym.Env, warn: bool = True, skip_render_check: bool = True) -
499488 f"Your action space has dtype { action_space .dtype } , we recommend using np.float32 to avoid cast errors."
500489 )
501490
502- # If Sequence observation space, do not check the observation any further
503- if isinstance ( observation_space , spaces . Sequence ) :
491+ # If Sequence or Graph observation space, do not check the observation any further
492+ if should_skip :
504493 return
505494
506495 # ============ Check the returned values ===============
@@ -512,12 +501,8 @@ def check_env(env: gym.Env, warn: bool = True, skip_render_check: bool = True) -
512501
513502 try :
514503 check_for_nested_spaces (env .observation_space )
515- # if there is None defined , then skip the test
516- if _is_graph_space (observation_space ) or (
517- isinstance (observation_space , spaces .Dict ) and any (_is_graph_space (s ) for s in observation_space .spaces .values ())
518- ):
519- pass # skip _check_nan for Graph spaces
520- else :
521- _check_nan (env )
504+ # The check doesn't support nested observations/dict actions
505+ # A warning about it has already been emitted
506+ _check_nan (env )
522507 except NotImplementedError :
523508 pass
0 commit comments