We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[docs/tune] Provide better documentation for reporter/results
### Describe the problem
The `reporter` object in function-based API is not well documented on the docs.

### Source code / logs
https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!msg/ray-dev/y4UXbSPoYaw/cLmdgq2nAwAJ


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `python/ray/tune/function_runner.py`
Content:
```
1 from __future__ import absolute_import
2 from __future__ import division
3 from __future__ import print_function
4 
5 import logging
6 import time
7 import threading
8 
9 from ray.tune import TuneError
10 from ray.tune.trainable import Trainable
11 from ray.tune.result import TIMESTEPS_TOTAL
12 
13 logger = logging.getLogger(__name__)
14 
15 
16 class StatusReporter(object):
17     """Object passed into your main() that you can report status through.
18 
19     Example:
20         >>> reporter = StatusReporter()
21         >>> reporter(timesteps_total=1)
22     """
23 
24     def __init__(self):
25         self._latest_result = None
26         self._last_result = None
27         self._lock = threading.Lock()
28         self._error = None
29         self._done = False
30 
31     def __call__(self, **kwargs):
32         """Report updated training status.
33 
34         Args:
35             kwargs: Latest training result status.
36         """
37 
38         with self._lock:
39             self._latest_result = self._last_result = kwargs.copy()
40 
41     def _get_and_clear_status(self):
42         if self._error:
43             raise TuneError("Error running trial: " + str(self._error))
44         if self._done and not self._latest_result:
45             if not self._last_result:
46                 raise TuneError("Trial finished without reporting result!")
47             self._last_result.update(done=True)
48             return self._last_result
49         with self._lock:
50             res = self._latest_result
51             self._latest_result = None
52             return res
53 
54     def _stop(self):
55         self._error = "Agent stopped"
56 
57 
58 DEFAULT_CONFIG = {
59     # batch results to at least this granularity
60     "script_min_iter_time_s": 1,
61 }
62 
63 
64 class _RunnerThread(threading.Thread):
65     """Supervisor thread that runs your script."""
66 
67     def __init__(self, entrypoint, config, status_reporter):
68         self._entrypoint = entrypoint
69         self._entrypoint_args = [config, status_reporter]
70         self._status_reporter = status_reporter
71         threading.Thread.__init__(self)
72         self.daemon = True
73 
74     def run(self):
75         try:
76             self._entrypoint(*self._entrypoint_args)
77         except Exception as e:
78             self._status_reporter._error = e
79             logger.exception("Runner Thread raised error.")
80             raise e
81         finally:
82             self._status_reporter._done = True
83 
84 
85 class FunctionRunner(Trainable):
86     """Trainable that runs a user function returning training results.
87 
88     This mode of execution does not support checkpoint/restore."""
89 
90     _name = "func"
91     _default_config = DEFAULT_CONFIG
92 
93     def _setup(self, config):
94         entrypoint = self._trainable_func()
95         self._status_reporter = StatusReporter()
96         scrubbed_config = config.copy()
97         for k in self._default_config:
98             if k in scrubbed_config:
99                 del scrubbed_config[k]
100         self._runner = _RunnerThread(entrypoint, scrubbed_config,
101                                      self._status_reporter)
102         self._start_time = time.time()
103         self._last_reported_timestep = 0
104         self._runner.start()
105 
106     def _trainable_func(self):
107         """Subclasses can override this to set the trainable func."""
108 
109         raise NotImplementedError
110 
111     def _train(self):
112         time.sleep(
113             self.config.get("script_min_iter_time_s",
114                             self._default_config["script_min_iter_time_s"]))
115         result = self._status_reporter._get_and_clear_status()
116         while result is None:
117             time.sleep(1)
118             result = self._status_reporter._get_and_clear_status()
119 
120         curr_ts_total = result.get(TIMESTEPS_TOTAL)
121         if curr_ts_total is not None:
122             result.update(
123                 timesteps_this_iter=(
124                     curr_ts_total - self._last_reported_timestep))
125             self._last_reported_timestep = curr_ts_total
126 
127         return result
128 
129     def _stop(self):
130         self._status_reporter._stop()
131
```

Path: `python/ray/tune/result.py`
Content:
```
1 from __future__ import absolute_import
2 from __future__ import division
3 from __future__ import print_function
4 
5 import os
6 
7 # (Optional/Auto-filled) training is terminated. Filled only if not provided.
8 DONE = "done"
9 
10 # (Auto-filled) The hostname of the machine hosting the training process.
11 HOSTNAME = "hostname"
12 
13 # (Auto-filled) The node ip of the machine hosting the training process.
14 NODE_IP = "node_ip"
15 
16 # (Auto-filled) The pid of the training process.
17 PID = "pid"
18 
19 # Number of episodes in this iteration.
20 EPISODES_THIS_ITER = "episodes_this_iter"
21 
22 # (Optional/Auto-filled) Accumulated number of episodes for this experiment.
23 EPISODES_TOTAL = "episodes_total"
24 
25 # Number of timesteps in this iteration.
26 TIMESTEPS_THIS_ITER = "timesteps_this_iter"
27 
28 # (Auto-filled) Accumulated number of timesteps for this entire experiment.
29 TIMESTEPS_TOTAL = "timesteps_total"
30 
31 # (Auto-filled) Time in seconds this iteration took to run.
32 # This may be overriden to override the system-computed time difference.
33 TIME_THIS_ITER_S = "time_this_iter_s"
34 
35 # (Auto-filled) Accumulated time in seconds for this entire experiment.
36 TIME_TOTAL_S = "time_total_s"
37 
38 # (Auto-filled) The index of this training iteration.
39 TRAINING_ITERATION = "training_iteration"
40 
41 # Where Tune writes result files by default
42 DEFAULT_RESULTS_DIR = (os.environ.get("TUNE_RESULT_DIR")
43                        or os.path.expanduser("~/ray_results"))
44 
45 # Meta file about status under each experiment directory, can be
46 # parsed by automlboard if exists.
47 JOB_META_FILE = "job_status.json"
48 
49 # Meta file about status under each trial directory, can be parsed
50 # by automlboard if exists.
51 EXPR_META_FILE = "trial_status.json"
52 
53 # File that stores parameters of the trial.
54 EXPR_PARARM_FILE = "params.json"
55 
56 # File that stores the progress of the trial.
57 EXPR_PROGRESS_FILE = "progress.csv"
58 
59 # File that stores results of the trial.
60 EXPR_RESULT_FILE = "result.json"
61
```
--- 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/python/ray/tune/function_runner.py b/python/ray/tune/function_runner.py
--- a/python/ray/tune/function_runner.py
+++ b/python/ray/tune/function_runner.py
@@ -14,11 +14,12 @@
 
 
 class StatusReporter(object):
-    """Object passed into your main() that you can report status through.
+    """Object passed into your function that you can report status through.
 
     Example:
-        >>> reporter = StatusReporter()
-        >>> reporter(timesteps_total=1)
+        >>> def trainable_function(config, reporter):
+        >>>     assert isinstance(reporter, StatusReporter)
+        >>>     reporter(timesteps_total=1)
     """
 
     def __init__(self):
@@ -33,6 +34,9 @@
 
         Args:
             kwargs: Latest training result status.
+
+        Example:
+            >>> reporter(mean_accuracy=1, training_iteration=4)
         """
 
         with self._lock:
diff --git a/python/ray/tune/result.py b/python/ray/tune/result.py
--- a/python/ray/tune/result.py
+++ b/python/ray/tune/result.py
@@ -4,6 +4,8 @@
 
 import os
 
+# yapf: disable
+# __sphinx_doc_begin__
 # (Optional/Auto-filled) training is terminated. Filled only if not provided.
 DONE = "done"
 
@@ -37,6 +39,8 @@
 
 # (Auto-filled) The index of this training iteration.
 TRAINING_ITERATION = "training_iteration"
+# __sphinx_doc_end__
+# yapf: enable
 
 # Where Tune writes result files by default
 DEFAULT_RESULTS_DIR = (os.environ.get("TUNE_RESULT_DIR")

{"golden_diff": "diff --git a/python/ray/tune/function_runner.py b/python/ray/tune/function_runner.py\n--- a/python/ray/tune/function_runner.py\n+++ b/python/ray/tune/function_runner.py\n@@ -14,11 +14,12 @@\n \n \n class StatusReporter(object):\n-    \"\"\"Object passed into your main() that you can report status through.\n+    \"\"\"Object passed into your function that you can report status through.\n \n     Example:\n-        >>> reporter = StatusReporter()\n-        >>> reporter(timesteps_total=1)\n+        >>> def trainable_function(config, reporter):\n+        >>>     assert isinstance(reporter, StatusReporter)\n+        >>>     reporter(timesteps_total=1)\n     \"\"\"\n \n     def __init__(self):\n@@ -33,6 +34,9 @@\n \n         Args:\n             kwargs: Latest training result status.\n+\n+        Example:\n+            >>> reporter(mean_accuracy=1, training_iteration=4)\n         \"\"\"\n \n         with self._lock:\ndiff --git a/python/ray/tune/result.py b/python/ray/tune/result.py\n--- a/python/ray/tune/result.py\n+++ b/python/ray/tune/result.py\n@@ -4,6 +4,8 @@\n \n import os\n \n+# yapf: disable\n+# __sphinx_doc_begin__\n # (Optional/Auto-filled) training is terminated. Filled only if not provided.\n DONE = \"done\"\n \n@@ -37,6 +39,8 @@\n \n # (Auto-filled) The index of this training iteration.\n TRAINING_ITERATION = \"training_iteration\"\n+# __sphinx_doc_end__\n+# yapf: enable\n \n # Where Tune writes result files by default\n DEFAULT_RESULTS_DIR = (os.environ.get(\"TUNE_RESULT_DIR\")\n", "issue": "[docs/tune] Provide better documentation for reporter/results\n### Describe the problem\r\nThe `reporter` object in function-based API is not well documented on the docs.\r\n\r\n### Source code / logs\r\nhttps://groups.google.com/forum/?utm_medium=email&utm_source=footer#!msg/ray-dev/y4UXbSPoYaw/cLmdgq2nAwAJ\r\n\n", "before_files": [{"content": "from __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\nimport logging\nimport time\nimport threading\n\nfrom ray.tune import TuneError\nfrom ray.tune.trainable import Trainable\nfrom ray.tune.result import TIMESTEPS_TOTAL\n\nlogger = logging.getLogger(__name__)\n\n\nclass StatusReporter(object):\n    \"\"\"Object passed into your main() that you can report status through.\n\n    Example:\n        >>> reporter = StatusReporter()\n        >>> reporter(timesteps_total=1)\n    \"\"\"\n\n    def __init__(self):\n        self._latest_result = None\n        self._last_result = None\n        self._lock = threading.Lock()\n        self._error = None\n        self._done = False\n\n    def __call__(self, **kwargs):\n        \"\"\"Report updated training status.\n\n        Args:\n            kwargs: Latest training result status.\n        \"\"\"\n\n        with self._lock:\n            self._latest_result = self._last_result = kwargs.copy()\n\n    def _get_and_clear_status(self):\n        if self._error:\n            raise TuneError(\"Error running trial: \" + str(self._error))\n        if self._done and not self._latest_result:\n            if not self._last_result:\n                raise TuneError(\"Trial finished without reporting result!\")\n            self._last_result.update(done=True)\n            return self._last_result\n        with self._lock:\n            res = self._latest_result\n            self._latest_result = None\n            return res\n\n    def _stop(self):\n        self._error = \"Agent stopped\"\n\n\nDEFAULT_CONFIG = {\n    # batch results to at least this granularity\n    \"script_min_iter_time_s\": 1,\n}\n\n\nclass _RunnerThread(threading.Thread):\n    \"\"\"Supervisor thread that runs your script.\"\"\"\n\n    def __init__(self, entrypoint, config, status_reporter):\n        self._entrypoint = entrypoint\n        self._entrypoint_args = [config, status_reporter]\n        self._status_reporter = status_reporter\n        threading.Thread.__init__(self)\n        self.daemon = True\n\n    def run(self):\n        try:\n            self._entrypoint(*self._entrypoint_args)\n        except Exception as e:\n            self._status_reporter._error = e\n            logger.exception(\"Runner Thread raised error.\")\n            raise e\n        finally:\n            self._status_reporter._done = True\n\n\nclass FunctionRunner(Trainable):\n    \"\"\"Trainable that runs a user function returning training results.\n\n    This mode of execution does not support checkpoint/restore.\"\"\"\n\n    _name = \"func\"\n    _default_config = DEFAULT_CONFIG\n\n    def _setup(self, config):\n        entrypoint = self._trainable_func()\n        self._status_reporter = StatusReporter()\n        scrubbed_config = config.copy()\n        for k in self._default_config:\n            if k in scrubbed_config:\n                del scrubbed_config[k]\n        self._runner = _RunnerThread(entrypoint, scrubbed_config,\n                                     self._status_reporter)\n        self._start_time = time.time()\n        self._last_reported_timestep = 0\n        self._runner.start()\n\n    def _trainable_func(self):\n        \"\"\"Subclasses can override this to set the trainable func.\"\"\"\n\n        raise NotImplementedError\n\n    def _train(self):\n        time.sleep(\n            self.config.get(\"script_min_iter_time_s\",\n                            self._default_config[\"script_min_iter_time_s\"]))\n        result = self._status_reporter._get_and_clear_status()\n        while result is None:\n            time.sleep(1)\n            result = self._status_reporter._get_and_clear_status()\n\n        curr_ts_total = result.get(TIMESTEPS_TOTAL)\n        if curr_ts_total is not None:\n            result.update(\n                timesteps_this_iter=(\n                    curr_ts_total - self._last_reported_timestep))\n            self._last_reported_timestep = curr_ts_total\n\n        return result\n\n    def _stop(self):\n        self._status_reporter._stop()\n", "path": "python/ray/tune/function_runner.py"}, {"content": "from __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\nimport os\n\n# (Optional/Auto-filled) training is terminated. Filled only if not provided.\nDONE = \"done\"\n\n# (Auto-filled) The hostname of the machine hosting the training process.\nHOSTNAME = \"hostname\"\n\n# (Auto-filled) The node ip of the machine hosting the training process.\nNODE_IP = \"node_ip\"\n\n# (Auto-filled) The pid of the training process.\nPID = \"pid\"\n\n# Number of episodes in this iteration.\nEPISODES_THIS_ITER = \"episodes_this_iter\"\n\n# (Optional/Auto-filled) Accumulated number of episodes for this experiment.\nEPISODES_TOTAL = \"episodes_total\"\n\n# Number of timesteps in this iteration.\nTIMESTEPS_THIS_ITER = \"timesteps_this_iter\"\n\n# (Auto-filled) Accumulated number of timesteps for this entire experiment.\nTIMESTEPS_TOTAL = \"timesteps_total\"\n\n# (Auto-filled) Time in seconds this iteration took to run.\n# This may be overriden to override the system-computed time difference.\nTIME_THIS_ITER_S = \"time_this_iter_s\"\n\n# (Auto-filled) Accumulated time in seconds for this entire experiment.\nTIME_TOTAL_S = \"time_total_s\"\n\n# (Auto-filled) The index of this training iteration.\nTRAINING_ITERATION = \"training_iteration\"\n\n# Where Tune writes result files by default\nDEFAULT_RESULTS_DIR = (os.environ.get(\"TUNE_RESULT_DIR\")\n                       or os.path.expanduser(\"~/ray_results\"))\n\n# Meta file about status under each experiment directory, can be\n# parsed by automlboard if exists.\nJOB_META_FILE = \"job_status.json\"\n\n# Meta file about status under each trial directory, can be parsed\n# by automlboard if exists.\nEXPR_META_FILE = \"trial_status.json\"\n\n# File that stores parameters of the trial.\nEXPR_PARARM_FILE = \"params.json\"\n\n# File that stores the progress of the trial.\nEXPR_PROGRESS_FILE = \"progress.csv\"\n\n# File that stores results of the trial.\nEXPR_RESULT_FILE = \"result.json\"\n", "path": "python/ray/tune/result.py"}], "after_files": [{"content": "from __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\nimport logging\nimport time\nimport threading\n\nfrom ray.tune import TuneError\nfrom ray.tune.trainable import Trainable\nfrom ray.tune.result import TIMESTEPS_TOTAL\n\nlogger = logging.getLogger(__name__)\n\n\nclass StatusReporter(object):\n    \"\"\"Object passed into your function that you can report status through.\n\n    Example:\n        >>> def trainable_function(config, reporter):\n        >>>     assert isinstance(reporter, StatusReporter)\n        >>>     reporter(timesteps_total=1)\n    \"\"\"\n\n    def __init__(self):\n        self._latest_result = None\n        self._last_result = None\n        self._lock = threading.Lock()\n        self._error = None\n        self._done = False\n\n    def __call__(self, **kwargs):\n        \"\"\"Report updated training status.\n\n        Args:\n            kwargs: Latest training result status.\n\n        Example:\n            >>> reporter(mean_accuracy=1, training_iteration=4)\n        \"\"\"\n\n        with self._lock:\n            self._latest_result = self._last_result = kwargs.copy()\n\n    def _get_and_clear_status(self):\n        if self._error:\n            raise TuneError(\"Error running trial: \" + str(self._error))\n        if self._done and not self._latest_result:\n            if not self._last_result:\n                raise TuneError(\"Trial finished without reporting result!\")\n            self._last_result.update(done=True)\n            return self._last_result\n        with self._lock:\n            res = self._latest_result\n            self._latest_result = None\n            return res\n\n    def _stop(self):\n        self._error = \"Agent stopped\"\n\n\nDEFAULT_CONFIG = {\n    # batch results to at least this granularity\n    \"script_min_iter_time_s\": 1,\n}\n\n\nclass _RunnerThread(threading.Thread):\n    \"\"\"Supervisor thread that runs your script.\"\"\"\n\n    def __init__(self, entrypoint, config, status_reporter):\n        self._entrypoint = entrypoint\n        self._entrypoint_args = [config, status_reporter]\n        self._status_reporter = status_reporter\n        threading.Thread.__init__(self)\n        self.daemon = True\n\n    def run(self):\n        try:\n            self._entrypoint(*self._entrypoint_args)\n        except Exception as e:\n            self._status_reporter._error = e\n            logger.exception(\"Runner Thread raised error.\")\n            raise e\n        finally:\n            self._status_reporter._done = True\n\n\nclass FunctionRunner(Trainable):\n    \"\"\"Trainable that runs a user function returning training results.\n\n    This mode of execution does not support checkpoint/restore.\"\"\"\n\n    _name = \"func\"\n    _default_config = DEFAULT_CONFIG\n\n    def _setup(self, config):\n        entrypoint = self._trainable_func()\n        self._status_reporter = StatusReporter()\n        scrubbed_config = config.copy()\n        for k in self._default_config:\n            if k in scrubbed_config:\n                del scrubbed_config[k]\n        self._runner = _RunnerThread(entrypoint, scrubbed_config,\n                                     self._status_reporter)\n        self._start_time = time.time()\n        self._last_reported_timestep = 0\n        self._runner.start()\n\n    def _trainable_func(self):\n        \"\"\"Subclasses can override this to set the trainable func.\"\"\"\n\n        raise NotImplementedError\n\n    def _train(self):\n        time.sleep(\n            self.config.get(\"script_min_iter_time_s\",\n                            self._default_config[\"script_min_iter_time_s\"]))\n        result = self._status_reporter._get_and_clear_status()\n        while result is None:\n            time.sleep(1)\n            result = self._status_reporter._get_and_clear_status()\n\n        curr_ts_total = result.get(TIMESTEPS_TOTAL)\n        if curr_ts_total is not None:\n            result.update(\n                timesteps_this_iter=(\n                    curr_ts_total - self._last_reported_timestep))\n            self._last_reported_timestep = curr_ts_total\n\n        return result\n\n    def _stop(self):\n        self._status_reporter._stop()\n", "path": "python/ray/tune/function_runner.py"}, {"content": "from __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\nimport os\n\n# yapf: disable\n# __sphinx_doc_begin__\n# (Optional/Auto-filled) training is terminated. Filled only if not provided.\nDONE = \"done\"\n\n# (Auto-filled) The hostname of the machine hosting the training process.\nHOSTNAME = \"hostname\"\n\n# (Auto-filled) The node ip of the machine hosting the training process.\nNODE_IP = \"node_ip\"\n\n# (Auto-filled) The pid of the training process.\nPID = \"pid\"\n\n# Number of episodes in this iteration.\nEPISODES_THIS_ITER = \"episodes_this_iter\"\n\n# (Optional/Auto-filled) Accumulated number of episodes for this experiment.\nEPISODES_TOTAL = \"episodes_total\"\n\n# Number of timesteps in this iteration.\nTIMESTEPS_THIS_ITER = \"timesteps_this_iter\"\n\n# (Auto-filled) Accumulated number of timesteps for this entire experiment.\nTIMESTEPS_TOTAL = \"timesteps_total\"\n\n# (Auto-filled) Time in seconds this iteration took to run.\n# This may be overriden to override the system-computed time difference.\nTIME_THIS_ITER_S = \"time_this_iter_s\"\n\n# (Auto-filled) Accumulated time in seconds for this entire experiment.\nTIME_TOTAL_S = \"time_total_s\"\n\n# (Auto-filled) The index of this training iteration.\nTRAINING_ITERATION = \"training_iteration\"\n# __sphinx_doc_end__\n# yapf: enable\n\n# Where Tune writes result files by default\nDEFAULT_RESULTS_DIR = (os.environ.get(\"TUNE_RESULT_DIR\")\n                       or os.path.expanduser(\"~/ray_results\"))\n\n# Meta file about status under each experiment directory, can be\n# parsed by automlboard if exists.\nJOB_META_FILE = \"job_status.json\"\n\n# Meta file about status under each trial directory, can be parsed\n# by automlboard if exists.\nEXPR_META_FILE = \"trial_status.json\"\n\n# File that stores parameters of the trial.\nEXPR_PARARM_FILE = \"params.json\"\n\n# File that stores the progress of the trial.\nEXPR_PROGRESS_FILE = \"progress.csv\"\n\n# File that stores results of the trial.\nEXPR_RESULT_FILE = \"result.json\"\n", "path": "python/ray/tune/result.py"}]}