We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[Question] Typo error in gym/core.py?
Greetings,

I'm trying to set up an environment from scratch and I noticed a potential error in the docstring of the step method of Env. Shouldn't the action argument come from the agent and not the environment( as stated in the docstring)? Or maybe I just understood something wrong.

Cheers

--- 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/core.py`
Content:
```
1 import gym
2 from gym import error
3 from gym.utils import closer
4 
5 env_closer = closer.Closer()
6 
7 
8 class Env(object):
9     r"""The main OpenAI Gym class. It encapsulates an environment with
10     arbitrary behind-the-scenes dynamics. An environment can be
11     partially or fully observed.
12 
13     The main API methods that users of this class need to know are:
14 
15         step
16         reset
17         render
18         close
19         seed
20 
21     And set the following attributes:
22 
23         action_space: The Space object corresponding to valid actions
24         observation_space: The Space object corresponding to valid observations
25         reward_range: A tuple corresponding to the min and max possible rewards
26 
27     Note: a default reward range set to [-inf,+inf] already exists. Set it if you want a narrower range.
28 
29     The methods are accessed publicly as "step", "reset", etc.. The
30     non-underscored versions are wrapper methods to which we may add
31     functionality over time.
32     """
33     # Set this in SOME subclasses
34     metadata = {'render.modes': []}
35     reward_range = (-float('inf'), float('inf'))
36     spec = None
37 
38     # Set these in ALL subclasses
39     action_space = None
40     observation_space = None
41 
42     def step(self, action):
43         """Run one timestep of the environment's dynamics. When end of
44         episode is reached, you are responsible for calling `reset()`
45         to reset this environment's state.
46 
47         Accepts an action and returns a tuple (observation, reward, done, info).
48 
49         Args:
50             action (object): an action provided by the environment
51 
52         Returns:
53             observation (object): agent's observation of the current environment
54             reward (float) : amount of reward returned after previous action
55             done (bool): whether the episode has ended, in which case further step() calls will return undefined results
56             info (dict): contains auxiliary diagnostic information (helpful for debugging, and sometimes learning)
57         """
58         raise NotImplementedError
59 
60     def reset(self):
61         """Resets the state of the environment and returns an initial observation.
62 
63         Returns: 
64             observation (object): the initial observation.
65         """
66         raise NotImplementedError
67 
68     def render(self, mode='human'):
69         """Renders the environment.
70 
71         The set of supported modes varies per environment. (And some
72         environments do not support rendering at all.) By convention,
73         if mode is:
74 
75         - human: render to the current display or terminal and
76           return nothing. Usually for human consumption.
77         - rgb_array: Return an numpy.ndarray with shape (x, y, 3),
78           representing RGB values for an x-by-y pixel image, suitable
79           for turning into a video.
80         - ansi: Return a string (str) or StringIO.StringIO containing a
81           terminal-style text representation. The text can include newlines
82           and ANSI escape sequences (e.g. for colors).
83 
84         Note:
85             Make sure that your class's metadata 'render.modes' key includes
86               the list of supported modes. It's recommended to call super()
87               in implementations to use the functionality of this method.
88 
89         Args:
90             mode (str): the mode to render with
91 
92         Example:
93 
94         class MyEnv(Env):
95             metadata = {'render.modes': ['human', 'rgb_array']}
96 
97             def render(self, mode='human'):
98                 if mode == 'rgb_array':
99                     return np.array(...) # return RGB frame suitable for video
100                 elif mode == 'human':
101                     ... # pop up a window and render
102                 else:
103                     super(MyEnv, self).render(mode=mode) # just raise an exception
104         """
105         raise NotImplementedError
106 
107     def close(self):
108         """Override close in your subclass to perform any necessary cleanup.
109 
110         Environments will automatically close() themselves when
111         garbage collected or when the program exits.
112         """
113         pass
114 
115     def seed(self, seed=None):
116         """Sets the seed for this env's random number generator(s).
117 
118         Note:
119             Some environments use multiple pseudorandom number generators.
120             We want to capture all such seeds used in order to ensure that
121             there aren't accidental correlations between multiple generators.
122 
123         Returns:
124             list<bigint>: Returns the list of seeds used in this env's random
125               number generators. The first value in the list should be the
126               "main" seed, or the value which a reproducer should pass to
127               'seed'. Often, the main seed equals the provided 'seed', but
128               this won't be true if seed=None, for example.
129         """
130         return
131 
132     @property
133     def unwrapped(self):
134         """Completely unwrap this env.
135 
136         Returns:
137             gym.Env: The base non-wrapped gym.Env instance
138         """
139         return self
140 
141     def __str__(self):
142         if self.spec is None:
143             return '<{} instance>'.format(type(self).__name__)
144         else:
145             return '<{}<{}>>'.format(type(self).__name__, self.spec.id)
146 
147     def __enter__(self):
148         return self
149 
150     def __exit__(self, *args):
151         self.close()
152         # propagate exception
153         return False
154 
155 
156 class GoalEnv(Env):
157     """A goal-based environment. It functions just as any regular OpenAI Gym environment but it
158     imposes a required structure on the observation_space. More concretely, the observation
159     space is required to contain at least three elements, namely `observation`, `desired_goal`, and
160     `achieved_goal`. Here, `desired_goal` specifies the goal that the agent should attempt to achieve.
161     `achieved_goal` is the goal that it currently achieved instead. `observation` contains the
162     actual observations of the environment as per usual.
163     """
164 
165     def reset(self):
166         # Enforce that each GoalEnv uses a Goal-compatible observation space.
167         if not isinstance(self.observation_space, gym.spaces.Dict):
168             raise error.Error('GoalEnv requires an observation space of type gym.spaces.Dict')
169         for key in ['observation', 'achieved_goal', 'desired_goal']:
170             if key not in self.observation_space.spaces:
171                 raise error.Error('GoalEnv requires the "{}" key to be part of the observation dictionary.'.format(key))
172 
173     def compute_reward(self, achieved_goal, desired_goal, info):
174         """Compute the step reward. This externalizes the reward function and makes
175         it dependent on an a desired goal and the one that was achieved. If you wish to include
176         additional rewards that are independent of the goal, you can include the necessary values
177         to derive it in info and compute it accordingly.
178 
179         Args:
180             achieved_goal (object): the goal that was achieved during execution
181             desired_goal (object): the desired goal that we asked the agent to attempt to achieve
182             info (dict): an info dictionary with additional information
183 
184         Returns:
185             float: The reward that corresponds to the provided achieved goal w.r.t. to the desired
186             goal. Note that the following should always hold true:
187 
188                 ob, reward, done, info = env.step()
189                 assert reward == env.compute_reward(ob['achieved_goal'], ob['goal'], info)
190         """
191         raise NotImplementedError
192 
193 
194 class Wrapper(Env):
195     r"""Wraps the environment to allow a modular transformation. 
196     
197     This class is the base class for all wrappers. The subclass could override
198     some methods to change the behavior of the original environment without touching the
199     original code. 
200     
201     .. note::
202     
203         Don't forget to call ``super().__init__(env)`` if the subclass overrides :meth:`__init__`.
204     
205     """
206     def __init__(self, env):
207         self.env = env
208         self.action_space = self.env.action_space
209         self.observation_space = self.env.observation_space
210         self.reward_range = self.env.reward_range
211         self.metadata = self.env.metadata
212         self.spec = getattr(self.env, 'spec', None)
213 
214     def __getattr__(self, name):
215         if name.startswith('_'):
216             raise AttributeError("attempted to get missing private attribute '{}'".format(name))
217         return getattr(self.env, name)
218 
219     @classmethod
220     def class_name(cls):
221         return cls.__name__
222 
223     def step(self, action):
224         return self.env.step(action)
225 
226     def reset(self, **kwargs):
227         return self.env.reset(**kwargs)
228 
229     def render(self, mode='human', **kwargs):
230         return self.env.render(mode, **kwargs)
231 
232     def close(self):
233         return self.env.close()
234 
235     def seed(self, seed=None):
236         return self.env.seed(seed)
237 
238     def compute_reward(self, achieved_goal, desired_goal, info):
239         return self.env.compute_reward(achieved_goal, desired_goal, info)
240 
241     def __str__(self):
242         return '<{}{}>'.format(type(self).__name__, self.env)
243 
244     def __repr__(self):
245         return str(self)
246 
247     @property
248     def unwrapped(self):
249         return self.env.unwrapped
250 
251 
252 class ObservationWrapper(Wrapper):
253     def reset(self, **kwargs):
254         observation = self.env.reset(**kwargs)
255         return self.observation(observation)
256 
257     def step(self, action):
258         observation, reward, done, info = self.env.step(action)
259         return self.observation(observation), reward, done, info
260 
261     def observation(self, observation):
262         raise NotImplementedError
263 
264 
265 class RewardWrapper(Wrapper):
266     def reset(self, **kwargs):
267         return self.env.reset(**kwargs)
268 
269     def step(self, action):
270         observation, reward, done, info = self.env.step(action)
271         return observation, self.reward(reward), done, info
272 
273     def reward(self, reward):
274         raise NotImplementedError
275 
276 
277 class ActionWrapper(Wrapper):
278     def reset(self, **kwargs):
279         return self.env.reset(**kwargs)
280 
281     def step(self, action):
282         return self.env.step(self.action(action))
283 
284     def action(self, action):
285         raise NotImplementedError
286 
287     def reverse_action(self, action):
288         raise NotImplementedError
289
```
--- 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/core.py b/gym/core.py
--- a/gym/core.py
+++ b/gym/core.py
@@ -47,7 +47,7 @@
         Accepts an action and returns a tuple (observation, reward, done, info).
 
         Args:
-            action (object): an action provided by the environment
+            action (object): an action provided by the agent
 
         Returns:
             observation (object): agent's observation of the current environment

{"golden_diff": "diff --git a/gym/core.py b/gym/core.py\n--- a/gym/core.py\n+++ b/gym/core.py\n@@ -47,7 +47,7 @@\n         Accepts an action and returns a tuple (observation, reward, done, info).\n \n         Args:\n-            action (object): an action provided by the environment\n+            action (object): an action provided by the agent\n \n         Returns:\n             observation (object): agent's observation of the current environment\n", "issue": "[Question] Typo error in gym/core.py?\nGreetings,\r\n\r\nI'm trying to set up an environment from scratch and I noticed a potential error in the docstring of the step method of Env. Shouldn't the action argument come from the agent and not the environment( as stated in the docstring)? Or maybe I just understood something wrong.\r\n\r\nCheers\n", "before_files": [{"content": "import gym\nfrom gym import error\nfrom gym.utils import closer\n\nenv_closer = closer.Closer()\n\n\nclass Env(object):\n    r\"\"\"The main OpenAI Gym class. It encapsulates an environment with\n    arbitrary behind-the-scenes dynamics. An environment can be\n    partially or fully observed.\n\n    The main API methods that users of this class need to know are:\n\n        step\n        reset\n        render\n        close\n        seed\n\n    And set the following attributes:\n\n        action_space: The Space object corresponding to valid actions\n        observation_space: The Space object corresponding to valid observations\n        reward_range: A tuple corresponding to the min and max possible rewards\n\n    Note: a default reward range set to [-inf,+inf] already exists. Set it if you want a narrower range.\n\n    The methods are accessed publicly as \"step\", \"reset\", etc.. The\n    non-underscored versions are wrapper methods to which we may add\n    functionality over time.\n    \"\"\"\n    # Set this in SOME subclasses\n    metadata = {'render.modes': []}\n    reward_range = (-float('inf'), float('inf'))\n    spec = None\n\n    # Set these in ALL subclasses\n    action_space = None\n    observation_space = None\n\n    def step(self, action):\n        \"\"\"Run one timestep of the environment's dynamics. When end of\n        episode is reached, you are responsible for calling `reset()`\n        to reset this environment's state.\n\n        Accepts an action and returns a tuple (observation, reward, done, info).\n\n        Args:\n            action (object): an action provided by the environment\n\n        Returns:\n            observation (object): agent's observation of the current environment\n            reward (float) : amount of reward returned after previous action\n            done (bool): whether the episode has ended, in which case further step() calls will return undefined results\n            info (dict): contains auxiliary diagnostic information (helpful for debugging, and sometimes learning)\n        \"\"\"\n        raise NotImplementedError\n\n    def reset(self):\n        \"\"\"Resets the state of the environment and returns an initial observation.\n\n        Returns: \n            observation (object): the initial observation.\n        \"\"\"\n        raise NotImplementedError\n\n    def render(self, mode='human'):\n        \"\"\"Renders the environment.\n\n        The set of supported modes varies per environment. (And some\n        environments do not support rendering at all.) By convention,\n        if mode is:\n\n        - human: render to the current display or terminal and\n          return nothing. Usually for human consumption.\n        - rgb_array: Return an numpy.ndarray with shape (x, y, 3),\n          representing RGB values for an x-by-y pixel image, suitable\n          for turning into a video.\n        - ansi: Return a string (str) or StringIO.StringIO containing a\n          terminal-style text representation. The text can include newlines\n          and ANSI escape sequences (e.g. for colors).\n\n        Note:\n            Make sure that your class's metadata 'render.modes' key includes\n              the list of supported modes. It's recommended to call super()\n              in implementations to use the functionality of this method.\n\n        Args:\n            mode (str): the mode to render with\n\n        Example:\n\n        class MyEnv(Env):\n            metadata = {'render.modes': ['human', 'rgb_array']}\n\n            def render(self, mode='human'):\n                if mode == 'rgb_array':\n                    return np.array(...) # return RGB frame suitable for video\n                elif mode == 'human':\n                    ... # pop up a window and render\n                else:\n                    super(MyEnv, self).render(mode=mode) # just raise an exception\n        \"\"\"\n        raise NotImplementedError\n\n    def close(self):\n        \"\"\"Override close in your subclass to perform any necessary cleanup.\n\n        Environments will automatically close() themselves when\n        garbage collected or when the program exits.\n        \"\"\"\n        pass\n\n    def seed(self, seed=None):\n        \"\"\"Sets the seed for this env's random number generator(s).\n\n        Note:\n            Some environments use multiple pseudorandom number generators.\n            We want to capture all such seeds used in order to ensure that\n            there aren't accidental correlations between multiple generators.\n\n        Returns:\n            list<bigint>: Returns the list of seeds used in this env's random\n              number generators. The first value in the list should be the\n              \"main\" seed, or the value which a reproducer should pass to\n              'seed'. Often, the main seed equals the provided 'seed', but\n              this won't be true if seed=None, for example.\n        \"\"\"\n        return\n\n    @property\n    def unwrapped(self):\n        \"\"\"Completely unwrap this env.\n\n        Returns:\n            gym.Env: The base non-wrapped gym.Env instance\n        \"\"\"\n        return self\n\n    def __str__(self):\n        if self.spec is None:\n            return '<{} instance>'.format(type(self).__name__)\n        else:\n            return '<{}<{}>>'.format(type(self).__name__, self.spec.id)\n\n    def __enter__(self):\n        return self\n\n    def __exit__(self, *args):\n        self.close()\n        # propagate exception\n        return False\n\n\nclass GoalEnv(Env):\n    \"\"\"A goal-based environment. It functions just as any regular OpenAI Gym environment but it\n    imposes a required structure on the observation_space. More concretely, the observation\n    space is required to contain at least three elements, namely `observation`, `desired_goal`, and\n    `achieved_goal`. Here, `desired_goal` specifies the goal that the agent should attempt to achieve.\n    `achieved_goal` is the goal that it currently achieved instead. `observation` contains the\n    actual observations of the environment as per usual.\n    \"\"\"\n\n    def reset(self):\n        # Enforce that each GoalEnv uses a Goal-compatible observation space.\n        if not isinstance(self.observation_space, gym.spaces.Dict):\n            raise error.Error('GoalEnv requires an observation space of type gym.spaces.Dict')\n        for key in ['observation', 'achieved_goal', 'desired_goal']:\n            if key not in self.observation_space.spaces:\n                raise error.Error('GoalEnv requires the \"{}\" key to be part of the observation dictionary.'.format(key))\n\n    def compute_reward(self, achieved_goal, desired_goal, info):\n        \"\"\"Compute the step reward. This externalizes the reward function and makes\n        it dependent on an a desired goal and the one that was achieved. If you wish to include\n        additional rewards that are independent of the goal, you can include the necessary values\n        to derive it in info and compute it accordingly.\n\n        Args:\n            achieved_goal (object): the goal that was achieved during execution\n            desired_goal (object): the desired goal that we asked the agent to attempt to achieve\n            info (dict): an info dictionary with additional information\n\n        Returns:\n            float: The reward that corresponds to the provided achieved goal w.r.t. to the desired\n            goal. Note that the following should always hold true:\n\n                ob, reward, done, info = env.step()\n                assert reward == env.compute_reward(ob['achieved_goal'], ob['goal'], info)\n        \"\"\"\n        raise NotImplementedError\n\n\nclass Wrapper(Env):\n    r\"\"\"Wraps the environment to allow a modular transformation. \n    \n    This class is the base class for all wrappers. The subclass could override\n    some methods to change the behavior of the original environment without touching the\n    original code. \n    \n    .. note::\n    \n        Don't forget to call ``super().__init__(env)`` if the subclass overrides :meth:`__init__`.\n    \n    \"\"\"\n    def __init__(self, env):\n        self.env = env\n        self.action_space = self.env.action_space\n        self.observation_space = self.env.observation_space\n        self.reward_range = self.env.reward_range\n        self.metadata = self.env.metadata\n        self.spec = getattr(self.env, 'spec', None)\n\n    def __getattr__(self, name):\n        if name.startswith('_'):\n            raise AttributeError(\"attempted to get missing private attribute '{}'\".format(name))\n        return getattr(self.env, name)\n\n    @classmethod\n    def class_name(cls):\n        return cls.__name__\n\n    def step(self, action):\n        return self.env.step(action)\n\n    def reset(self, **kwargs):\n        return self.env.reset(**kwargs)\n\n    def render(self, mode='human', **kwargs):\n        return self.env.render(mode, **kwargs)\n\n    def close(self):\n        return self.env.close()\n\n    def seed(self, seed=None):\n        return self.env.seed(seed)\n\n    def compute_reward(self, achieved_goal, desired_goal, info):\n        return self.env.compute_reward(achieved_goal, desired_goal, info)\n\n    def __str__(self):\n        return '<{}{}>'.format(type(self).__name__, self.env)\n\n    def __repr__(self):\n        return str(self)\n\n    @property\n    def unwrapped(self):\n        return self.env.unwrapped\n\n\nclass ObservationWrapper(Wrapper):\n    def reset(self, **kwargs):\n        observation = self.env.reset(**kwargs)\n        return self.observation(observation)\n\n    def step(self, action):\n        observation, reward, done, info = self.env.step(action)\n        return self.observation(observation), reward, done, info\n\n    def observation(self, observation):\n        raise NotImplementedError\n\n\nclass RewardWrapper(Wrapper):\n    def reset(self, **kwargs):\n        return self.env.reset(**kwargs)\n\n    def step(self, action):\n        observation, reward, done, info = self.env.step(action)\n        return observation, self.reward(reward), done, info\n\n    def reward(self, reward):\n        raise NotImplementedError\n\n\nclass ActionWrapper(Wrapper):\n    def reset(self, **kwargs):\n        return self.env.reset(**kwargs)\n\n    def step(self, action):\n        return self.env.step(self.action(action))\n\n    def action(self, action):\n        raise NotImplementedError\n\n    def reverse_action(self, action):\n        raise NotImplementedError\n", "path": "gym/core.py"}], "after_files": [{"content": "import gym\nfrom gym import error\nfrom gym.utils import closer\n\nenv_closer = closer.Closer()\n\n\nclass Env(object):\n    r\"\"\"The main OpenAI Gym class. It encapsulates an environment with\n    arbitrary behind-the-scenes dynamics. An environment can be\n    partially or fully observed.\n\n    The main API methods that users of this class need to know are:\n\n        step\n        reset\n        render\n        close\n        seed\n\n    And set the following attributes:\n\n        action_space: The Space object corresponding to valid actions\n        observation_space: The Space object corresponding to valid observations\n        reward_range: A tuple corresponding to the min and max possible rewards\n\n    Note: a default reward range set to [-inf,+inf] already exists. Set it if you want a narrower range.\n\n    The methods are accessed publicly as \"step\", \"reset\", etc.. The\n    non-underscored versions are wrapper methods to which we may add\n    functionality over time.\n    \"\"\"\n    # Set this in SOME subclasses\n    metadata = {'render.modes': []}\n    reward_range = (-float('inf'), float('inf'))\n    spec = None\n\n    # Set these in ALL subclasses\n    action_space = None\n    observation_space = None\n\n    def step(self, action):\n        \"\"\"Run one timestep of the environment's dynamics. When end of\n        episode is reached, you are responsible for calling `reset()`\n        to reset this environment's state.\n\n        Accepts an action and returns a tuple (observation, reward, done, info).\n\n        Args:\n            action (object): an action provided by the agent\n\n        Returns:\n            observation (object): agent's observation of the current environment\n            reward (float) : amount of reward returned after previous action\n            done (bool): whether the episode has ended, in which case further step() calls will return undefined results\n            info (dict): contains auxiliary diagnostic information (helpful for debugging, and sometimes learning)\n        \"\"\"\n        raise NotImplementedError\n\n    def reset(self):\n        \"\"\"Resets the state of the environment and returns an initial observation.\n\n        Returns: \n            observation (object): the initial observation.\n        \"\"\"\n        raise NotImplementedError\n\n    def render(self, mode='human'):\n        \"\"\"Renders the environment.\n\n        The set of supported modes varies per environment. (And some\n        environments do not support rendering at all.) By convention,\n        if mode is:\n\n        - human: render to the current display or terminal and\n          return nothing. Usually for human consumption.\n        - rgb_array: Return an numpy.ndarray with shape (x, y, 3),\n          representing RGB values for an x-by-y pixel image, suitable\n          for turning into a video.\n        - ansi: Return a string (str) or StringIO.StringIO containing a\n          terminal-style text representation. The text can include newlines\n          and ANSI escape sequences (e.g. for colors).\n\n        Note:\n            Make sure that your class's metadata 'render.modes' key includes\n              the list of supported modes. It's recommended to call super()\n              in implementations to use the functionality of this method.\n\n        Args:\n            mode (str): the mode to render with\n\n        Example:\n\n        class MyEnv(Env):\n            metadata = {'render.modes': ['human', 'rgb_array']}\n\n            def render(self, mode='human'):\n                if mode == 'rgb_array':\n                    return np.array(...) # return RGB frame suitable for video\n                elif mode == 'human':\n                    ... # pop up a window and render\n                else:\n                    super(MyEnv, self).render(mode=mode) # just raise an exception\n        \"\"\"\n        raise NotImplementedError\n\n    def close(self):\n        \"\"\"Override close in your subclass to perform any necessary cleanup.\n\n        Environments will automatically close() themselves when\n        garbage collected or when the program exits.\n        \"\"\"\n        pass\n\n    def seed(self, seed=None):\n        \"\"\"Sets the seed for this env's random number generator(s).\n\n        Note:\n            Some environments use multiple pseudorandom number generators.\n            We want to capture all such seeds used in order to ensure that\n            there aren't accidental correlations between multiple generators.\n\n        Returns:\n            list<bigint>: Returns the list of seeds used in this env's random\n              number generators. The first value in the list should be the\n              \"main\" seed, or the value which a reproducer should pass to\n              'seed'. Often, the main seed equals the provided 'seed', but\n              this won't be true if seed=None, for example.\n        \"\"\"\n        return\n\n    @property\n    def unwrapped(self):\n        \"\"\"Completely unwrap this env.\n\n        Returns:\n            gym.Env: The base non-wrapped gym.Env instance\n        \"\"\"\n        return self\n\n    def __str__(self):\n        if self.spec is None:\n            return '<{} instance>'.format(type(self).__name__)\n        else:\n            return '<{}<{}>>'.format(type(self).__name__, self.spec.id)\n\n    def __enter__(self):\n        return self\n\n    def __exit__(self, *args):\n        self.close()\n        # propagate exception\n        return False\n\n\nclass GoalEnv(Env):\n    \"\"\"A goal-based environment. It functions just as any regular OpenAI Gym environment but it\n    imposes a required structure on the observation_space. More concretely, the observation\n    space is required to contain at least three elements, namely `observation`, `desired_goal`, and\n    `achieved_goal`. Here, `desired_goal` specifies the goal that the agent should attempt to achieve.\n    `achieved_goal` is the goal that it currently achieved instead. `observation` contains the\n    actual observations of the environment as per usual.\n    \"\"\"\n\n    def reset(self):\n        # Enforce that each GoalEnv uses a Goal-compatible observation space.\n        if not isinstance(self.observation_space, gym.spaces.Dict):\n            raise error.Error('GoalEnv requires an observation space of type gym.spaces.Dict')\n        for key in ['observation', 'achieved_goal', 'desired_goal']:\n            if key not in self.observation_space.spaces:\n                raise error.Error('GoalEnv requires the \"{}\" key to be part of the observation dictionary.'.format(key))\n\n    def compute_reward(self, achieved_goal, desired_goal, info):\n        \"\"\"Compute the step reward. This externalizes the reward function and makes\n        it dependent on an a desired goal and the one that was achieved. If you wish to include\n        additional rewards that are independent of the goal, you can include the necessary values\n        to derive it in info and compute it accordingly.\n\n        Args:\n            achieved_goal (object): the goal that was achieved during execution\n            desired_goal (object): the desired goal that we asked the agent to attempt to achieve\n            info (dict): an info dictionary with additional information\n\n        Returns:\n            float: The reward that corresponds to the provided achieved goal w.r.t. to the desired\n            goal. Note that the following should always hold true:\n\n                ob, reward, done, info = env.step()\n                assert reward == env.compute_reward(ob['achieved_goal'], ob['goal'], info)\n        \"\"\"\n        raise NotImplementedError\n\n\nclass Wrapper(Env):\n    r\"\"\"Wraps the environment to allow a modular transformation. \n    \n    This class is the base class for all wrappers. The subclass could override\n    some methods to change the behavior of the original environment without touching the\n    original code. \n    \n    .. note::\n    \n        Don't forget to call ``super().__init__(env)`` if the subclass overrides :meth:`__init__`.\n    \n    \"\"\"\n    def __init__(self, env):\n        self.env = env\n        self.action_space = self.env.action_space\n        self.observation_space = self.env.observation_space\n        self.reward_range = self.env.reward_range\n        self.metadata = self.env.metadata\n        self.spec = getattr(self.env, 'spec', None)\n\n    def __getattr__(self, name):\n        if name.startswith('_'):\n            raise AttributeError(\"attempted to get missing private attribute '{}'\".format(name))\n        return getattr(self.env, name)\n\n    @classmethod\n    def class_name(cls):\n        return cls.__name__\n\n    def step(self, action):\n        return self.env.step(action)\n\n    def reset(self, **kwargs):\n        return self.env.reset(**kwargs)\n\n    def render(self, mode='human', **kwargs):\n        return self.env.render(mode, **kwargs)\n\n    def close(self):\n        return self.env.close()\n\n    def seed(self, seed=None):\n        return self.env.seed(seed)\n\n    def compute_reward(self, achieved_goal, desired_goal, info):\n        return self.env.compute_reward(achieved_goal, desired_goal, info)\n\n    def __str__(self):\n        return '<{}{}>'.format(type(self).__name__, self.env)\n\n    def __repr__(self):\n        return str(self)\n\n    @property\n    def unwrapped(self):\n        return self.env.unwrapped\n\n\nclass ObservationWrapper(Wrapper):\n    def reset(self, **kwargs):\n        observation = self.env.reset(**kwargs)\n        return self.observation(observation)\n\n    def step(self, action):\n        observation, reward, done, info = self.env.step(action)\n        return self.observation(observation), reward, done, info\n\n    def observation(self, observation):\n        raise NotImplementedError\n\n\nclass RewardWrapper(Wrapper):\n    def reset(self, **kwargs):\n        return self.env.reset(**kwargs)\n\n    def step(self, action):\n        observation, reward, done, info = self.env.step(action)\n        return observation, self.reward(reward), done, info\n\n    def reward(self, reward):\n        raise NotImplementedError\n\n\nclass ActionWrapper(Wrapper):\n    def reset(self, **kwargs):\n        return self.env.reset(**kwargs)\n\n    def step(self, action):\n        return self.env.step(self.action(action))\n\n    def action(self, action):\n        raise NotImplementedError\n\n    def reverse_action(self, action):\n        raise NotImplementedError\n", "path": "gym/core.py"}]}