prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  [RFC] Show progress bar based on `timeout`
  <!-- Please write a clear and concise description of the feature proposal. -->
  
  ## Motivation
  
  The current [`study.optimize`](https://optuna.readthedocs.io/en/stable/reference/generated/optuna.study.Study.html#optuna.study.Study.optimize) shows the progress bar when we specify the number of trials. We can show the progress bar based on the `timeout` value as well.
  
  Note that before implementing this feature, we need to decide the priority of `n_trials` and `timeout`. When we specify both values as not `None` values, there are two ways to show the progress bar. 
  
  Moreover, we need to discuss the case when both `None`. I suppose not showing the progress bar makes sense when both are `None`.
  
  ## Description
  
  <!-- Please write a detailed description of the new feature. -->
  
  
  - Show progress bar using `timeout` value.
  - Add test by following https://github.com/optuna/optuna/pull/2900
  
  ## Alternatives (optional)
  
  
  <!-- Please write a clear and concise description of any alternative solutions or features you've considered. -->
  
  ## Additional context (optional)
  
  We might need to support the `n_jobs!=1` case depending on https://github.com/optuna/optuna/issues/2957.
  
  <!-- Please add any other context or screenshots about the feature request here. -->
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `optuna/progress_bar.py`
  Content:
  ```
  1 import logging
  2 from typing import Any
  3 from typing import Optional
  4 
  5 from tqdm.auto import tqdm
  6 
  7 from optuna import logging as optuna_logging
  8 from optuna._experimental import experimental
  9 
  10 
  11 _tqdm_handler: Optional["_TqdmLoggingHandler"] = None
  12 
  13 
  14 # Reference: https://gist.github.com/hvy/8b80c2cedf02b15c24f85d1fa17ebe02
  15 class _TqdmLoggingHandler(logging.StreamHandler):
  16     def emit(self, record: Any) -> None:
  17         try:
  18             msg = self.format(record)
  19             tqdm.write(msg)
  20             self.flush()
  21         except (KeyboardInterrupt, SystemExit):
  22             raise
  23         except Exception:
  24             self.handleError(record)
  25 
  26 
  27 class _ProgressBar(object):
  28     """Progress Bar implementation for :func:`~optuna.study.Study.optimize` on the top of `tqdm`.
  29 
  30     Args:
  31         is_valid:
  32             Whether to show progress bars in :func:`~optuna.study.Study.optimize`.
  33         n_trials:
  34             The number of trials.
  35         timeout:
  36             Stop study after the given number of second(s).
  37     """
  38 
  39     def __init__(
  40         self, is_valid: bool, n_trials: Optional[int] = None, timeout: Optional[float] = None
  41     ) -> None:
  42         self._is_valid = is_valid
  43         self._n_trials = n_trials
  44         self._timeout = timeout
  45 
  46         if self._is_valid:
  47             self._init_valid()
  48 
  49     # TODO(hvy): Remove initialization indirection via this method when the progress bar is no
  50     # longer experimental.
  51     @experimental("1.2.0", name="Progress bar")
  52     def _init_valid(self) -> None:
  53         self._progress_bar = tqdm(range(self._n_trials) if self._n_trials is not None else None)
  54         global _tqdm_handler
  55 
  56         _tqdm_handler = _TqdmLoggingHandler()
  57         _tqdm_handler.setLevel(logging.INFO)
  58         _tqdm_handler.setFormatter(optuna_logging.create_default_formatter())
  59         optuna_logging.disable_default_handler()
  60         optuna_logging._get_library_root_logger().addHandler(_tqdm_handler)
  61 
  62     def update(self, elapsed_seconds: Optional[float]) -> None:
  63         """Update the progress bars if ``is_valid`` is :obj:`True`.
  64 
  65         Args:
  66             elapsed_seconds:
  67                 The time past since :func:`~optuna.study.Study.optimize` started.
  68         """
  69         if self._is_valid:
  70             self._progress_bar.update(1)
  71             if self._timeout is not None and elapsed_seconds is not None:
  72                 self._progress_bar.set_postfix_str(
  73                     "{:.02f}/{} seconds".format(elapsed_seconds, self._timeout)
  74                 )
  75 
  76     def close(self) -> None:
  77         """Close progress bars."""
  78         if self._is_valid:
  79             self._progress_bar.close()
  80             assert _tqdm_handler is not None
  81             optuna_logging._get_library_root_logger().removeHandler(_tqdm_handler)
  82             optuna_logging.enable_default_handler()
  83
  ```
  --- 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()
  
  ```
  
golden_diff: diff --git a/optuna/progress_bar.py b/optuna/progress_bar.py
  --- a/optuna/progress_bar.py
  +++ b/optuna/progress_bar.py
  @@ -39,9 +39,11 @@
       def __init__(
           self, is_valid: bool, n_trials: Optional[int] = None, timeout: Optional[float] = None
       ) -> None:
  -        self._is_valid = is_valid
  +
  +        self._is_valid = is_valid and (n_trials or timeout) is not None
           self._n_trials = n_trials
           self._timeout = timeout
  +        self._last_elapsed_seconds = 0.0
   
           if self._is_valid:
               self._init_valid()
  @@ -50,7 +52,21 @@
       # longer experimental.
       @experimental("1.2.0", name="Progress bar")
       def _init_valid(self) -> None:
  -        self._progress_bar = tqdm(range(self._n_trials) if self._n_trials is not None else None)
  +
  +        if self._n_trials is not None:
  +            self._progress_bar = tqdm(total=self._n_trials)
  +
  +        else:
  +            fmt = "{percentage:3.0f}%|{bar}| {elapsed}/{desc}"
  +            self._progress_bar = tqdm(total=self._timeout, bar_format=fmt)
  +
  +            # Using description string instead postfix string
  +            # to display formatted timeout, since postfix carries
  +            # extra comma space auto-format.
  +            # https://github.com/tqdm/tqdm/issues/712
  +            total = tqdm.format_interval(self._timeout)
  +            self._progress_bar.set_description_str(total)
  +
           global _tqdm_handler
   
           _tqdm_handler = _TqdmLoggingHandler()
  @@ -59,22 +75,37 @@
           optuna_logging.disable_default_handler()
           optuna_logging._get_library_root_logger().addHandler(_tqdm_handler)
   
  -    def update(self, elapsed_seconds: Optional[float]) -> None:
  +    def update(self, elapsed_seconds: float) -> None:
           """Update the progress bars if ``is_valid`` is :obj:`True`.
   
           Args:
               elapsed_seconds:
                   The time past since :func:`~optuna.study.Study.optimize` started.
           """
  +
           if self._is_valid:
  -            self._progress_bar.update(1)
  -            if self._timeout is not None and elapsed_seconds is not None:
  -                self._progress_bar.set_postfix_str(
  -                    "{:.02f}/{} seconds".format(elapsed_seconds, self._timeout)
  -                )
  +            if self._n_trials is not None:
  +                self._progress_bar.update(1)
  +                if self._timeout is not None:
  +                    self._progress_bar.set_postfix_str(
  +                        "{:.02f}/{} seconds".format(elapsed_seconds, self._timeout)
  +                    )
  +
  +            elif self._timeout is not None:
  +                time_diff = elapsed_seconds - self._last_elapsed_seconds
  +                if elapsed_seconds > self._timeout:
  +                    # Clip elapsed time to avoid tqdm warnings.
  +                    time_diff -= elapsed_seconds - self._timeout
  +
  +                self._progress_bar.update(time_diff)
  +                self._last_elapsed_seconds = elapsed_seconds
  +
  +            else:
  +                assert False
   
       def close(self) -> None:
           """Close progress bars."""
  +
           if self._is_valid:
               self._progress_bar.close()
               assert _tqdm_handler is not None
  
verification_info: {"golden_diff": "diff --git a/optuna/progress_bar.py b/optuna/progress_bar.py\n--- a/optuna/progress_bar.py\n+++ b/optuna/progress_bar.py\n@@ -39,9 +39,11 @@\n     def __init__(\n         self, is_valid: bool, n_trials: Optional[int] = None, timeout: Optional[float] = None\n     ) -> None:\n-        self._is_valid = is_valid\n+\n+        self._is_valid = is_valid and (n_trials or timeout) is not None\n         self._n_trials = n_trials\n         self._timeout = timeout\n+        self._last_elapsed_seconds = 0.0\n \n         if self._is_valid:\n             self._init_valid()\n@@ -50,7 +52,21 @@\n     # longer experimental.\n     @experimental(\"1.2.0\", name=\"Progress bar\")\n     def _init_valid(self) -> None:\n-        self._progress_bar = tqdm(range(self._n_trials) if self._n_trials is not None else None)\n+\n+        if self._n_trials is not None:\n+            self._progress_bar = tqdm(total=self._n_trials)\n+\n+        else:\n+            fmt = \"{percentage:3.0f}%|{bar}| {elapsed}/{desc}\"\n+            self._progress_bar = tqdm(total=self._timeout, bar_format=fmt)\n+\n+            # Using description string instead postfix string\n+            # to display formatted timeout, since postfix carries\n+            # extra comma space auto-format.\n+            # https://github.com/tqdm/tqdm/issues/712\n+            total = tqdm.format_interval(self._timeout)\n+            self._progress_bar.set_description_str(total)\n+\n         global _tqdm_handler\n \n         _tqdm_handler = _TqdmLoggingHandler()\n@@ -59,22 +75,37 @@\n         optuna_logging.disable_default_handler()\n         optuna_logging._get_library_root_logger().addHandler(_tqdm_handler)\n \n-    def update(self, elapsed_seconds: Optional[float]) -> None:\n+    def update(self, elapsed_seconds: float) -> None:\n         \"\"\"Update the progress bars if ``is_valid`` is :obj:`True`.\n \n         Args:\n             elapsed_seconds:\n                 The time past since :func:`~optuna.study.Study.optimize` started.\n         \"\"\"\n+\n         if self._is_valid:\n-            self._progress_bar.update(1)\n-            if self._timeout is not None and elapsed_seconds is not None:\n-                self._progress_bar.set_postfix_str(\n-                    \"{:.02f}/{} seconds\".format(elapsed_seconds, self._timeout)\n-                )\n+            if self._n_trials is not None:\n+                self._progress_bar.update(1)\n+                if self._timeout is not None:\n+                    self._progress_bar.set_postfix_str(\n+                        \"{:.02f}/{} seconds\".format(elapsed_seconds, self._timeout)\n+                    )\n+\n+            elif self._timeout is not None:\n+                time_diff = elapsed_seconds - self._last_elapsed_seconds\n+                if elapsed_seconds > self._timeout:\n+                    # Clip elapsed time to avoid tqdm warnings.\n+                    time_diff -= elapsed_seconds - self._timeout\n+\n+                self._progress_bar.update(time_diff)\n+                self._last_elapsed_seconds = elapsed_seconds\n+\n+            else:\n+                assert False\n \n     def close(self) -> None:\n         \"\"\"Close progress bars.\"\"\"\n+\n         if self._is_valid:\n             self._progress_bar.close()\n             assert _tqdm_handler is not None\n", "issue": "[RFC] Show progress bar based on `timeout`\n<!-- Please write a clear and concise description of the feature proposal. -->\r\n\r\n## Motivation\r\n\r\nThe current [`study.optimize`](https://optuna.readthedocs.io/en/stable/reference/generated/optuna.study.Study.html#optuna.study.Study.optimize) shows the progress bar when we specify the number of trials. We can show the progress bar based on the `timeout` value as well.\r\n\r\nNote that before implementing this feature, we need to decide the priority of `n_trials` and `timeout`. When we specify both values as not `None` values, there are two ways to show the progress bar. \r\n\r\nMoreover, we need to discuss the case when both `None`. I suppose not showing the progress bar makes sense when both are `None`.\r\n\r\n## Description\r\n\r\n<!-- Please write a detailed description of the new feature. -->\r\n\r\n\r\n- Show progress bar using `timeout` value.\r\n- Add test by following https://github.com/optuna/optuna/pull/2900\r\n\r\n## Alternatives (optional)\r\n\r\n\r\n<!-- Please write a clear and concise description of any alternative solutions or features you've considered. -->\r\n\r\n## Additional context (optional)\r\n\r\nWe might need to support the `n_jobs!=1` case depending on https://github.com/optuna/optuna/issues/2957.\r\n\r\n<!-- Please add any other context or screenshots about the feature request here. -->\r\n\n", "before_files": [{"content": "import logging\nfrom typing import Any\nfrom typing import Optional\n\nfrom tqdm.auto import tqdm\n\nfrom optuna import logging as optuna_logging\nfrom optuna._experimental import experimental\n\n\n_tqdm_handler: Optional[\"_TqdmLoggingHandler\"] = None\n\n\n# Reference: https://gist.github.com/hvy/8b80c2cedf02b15c24f85d1fa17ebe02\nclass _TqdmLoggingHandler(logging.StreamHandler):\n    def emit(self, record: Any) -> None:\n        try:\n            msg = self.format(record)\n            tqdm.write(msg)\n            self.flush()\n        except (KeyboardInterrupt, SystemExit):\n            raise\n        except Exception:\n            self.handleError(record)\n\n\nclass _ProgressBar(object):\n    \"\"\"Progress Bar implementation for :func:`~optuna.study.Study.optimize` on the top of `tqdm`.\n\n    Args:\n        is_valid:\n            Whether to show progress bars in :func:`~optuna.study.Study.optimize`.\n        n_trials:\n            The number of trials.\n        timeout:\n            Stop study after the given number of second(s).\n    \"\"\"\n\n    def __init__(\n        self, is_valid: bool, n_trials: Optional[int] = None, timeout: Optional[float] = None\n    ) -> None:\n        self._is_valid = is_valid\n        self._n_trials = n_trials\n        self._timeout = timeout\n\n        if self._is_valid:\n            self._init_valid()\n\n    # TODO(hvy): Remove initialization indirection via this method when the progress bar is no\n    # longer experimental.\n    @experimental(\"1.2.0\", name=\"Progress bar\")\n    def _init_valid(self) -> None:\n        self._progress_bar = tqdm(range(self._n_trials) if self._n_trials is not None else None)\n        global _tqdm_handler\n\n        _tqdm_handler = _TqdmLoggingHandler()\n        _tqdm_handler.setLevel(logging.INFO)\n        _tqdm_handler.setFormatter(optuna_logging.create_default_formatter())\n        optuna_logging.disable_default_handler()\n        optuna_logging._get_library_root_logger().addHandler(_tqdm_handler)\n\n    def update(self, elapsed_seconds: Optional[float]) -> None:\n        \"\"\"Update the progress bars if ``is_valid`` is :obj:`True`.\n\n        Args:\n            elapsed_seconds:\n                The time past since :func:`~optuna.study.Study.optimize` started.\n        \"\"\"\n        if self._is_valid:\n            self._progress_bar.update(1)\n            if self._timeout is not None and elapsed_seconds is not None:\n                self._progress_bar.set_postfix_str(\n                    \"{:.02f}/{} seconds\".format(elapsed_seconds, self._timeout)\n                )\n\n    def close(self) -> None:\n        \"\"\"Close progress bars.\"\"\"\n        if self._is_valid:\n            self._progress_bar.close()\n            assert _tqdm_handler is not None\n            optuna_logging._get_library_root_logger().removeHandler(_tqdm_handler)\n            optuna_logging.enable_default_handler()\n", "path": "optuna/progress_bar.py"}], "after_files": [{"content": "import logging\nfrom typing import Any\nfrom typing import Optional\n\nfrom tqdm.auto import tqdm\n\nfrom optuna import logging as optuna_logging\nfrom optuna._experimental import experimental\n\n\n_tqdm_handler: Optional[\"_TqdmLoggingHandler\"] = None\n\n\n# Reference: https://gist.github.com/hvy/8b80c2cedf02b15c24f85d1fa17ebe02\nclass _TqdmLoggingHandler(logging.StreamHandler):\n    def emit(self, record: Any) -> None:\n        try:\n            msg = self.format(record)\n            tqdm.write(msg)\n            self.flush()\n        except (KeyboardInterrupt, SystemExit):\n            raise\n        except Exception:\n            self.handleError(record)\n\n\nclass _ProgressBar(object):\n    \"\"\"Progress Bar implementation for :func:`~optuna.study.Study.optimize` on the top of `tqdm`.\n\n    Args:\n        is_valid:\n            Whether to show progress bars in :func:`~optuna.study.Study.optimize`.\n        n_trials:\n            The number of trials.\n        timeout:\n            Stop study after the given number of second(s).\n    \"\"\"\n\n    def __init__(\n        self, is_valid: bool, n_trials: Optional[int] = None, timeout: Optional[float] = None\n    ) -> None:\n\n        self._is_valid = is_valid and (n_trials or timeout) is not None\n        self._n_trials = n_trials\n        self._timeout = timeout\n        self._last_elapsed_seconds = 0.0\n\n        if self._is_valid:\n            self._init_valid()\n\n    # TODO(hvy): Remove initialization indirection via this method when the progress bar is no\n    # longer experimental.\n    @experimental(\"1.2.0\", name=\"Progress bar\")\n    def _init_valid(self) -> None:\n\n        if self._n_trials is not None:\n            self._progress_bar = tqdm(total=self._n_trials)\n\n        else:\n            fmt = \"{percentage:3.0f}%|{bar}| {elapsed}/{desc}\"\n            self._progress_bar = tqdm(total=self._timeout, bar_format=fmt)\n\n            # Using description string instead postfix string\n            # to display formatted timeout, since postfix carries\n            # extra comma space auto-format.\n            # https://github.com/tqdm/tqdm/issues/712\n            total = tqdm.format_interval(self._timeout)\n            self._progress_bar.set_description_str(total)\n\n        global _tqdm_handler\n\n        _tqdm_handler = _TqdmLoggingHandler()\n        _tqdm_handler.setLevel(logging.INFO)\n        _tqdm_handler.setFormatter(optuna_logging.create_default_formatter())\n        optuna_logging.disable_default_handler()\n        optuna_logging._get_library_root_logger().addHandler(_tqdm_handler)\n\n    def update(self, elapsed_seconds: float) -> None:\n        \"\"\"Update the progress bars if ``is_valid`` is :obj:`True`.\n\n        Args:\n            elapsed_seconds:\n                The time past since :func:`~optuna.study.Study.optimize` started.\n        \"\"\"\n\n        if self._is_valid:\n            if self._n_trials is not None:\n                self._progress_bar.update(1)\n                if self._timeout is not None:\n                    self._progress_bar.set_postfix_str(\n                        \"{:.02f}/{} seconds\".format(elapsed_seconds, self._timeout)\n                    )\n\n            elif self._timeout is not None:\n                time_diff = elapsed_seconds - self._last_elapsed_seconds\n                if elapsed_seconds > self._timeout:\n                    # Clip elapsed time to avoid tqdm warnings.\n                    time_diff -= elapsed_seconds - self._timeout\n\n                self._progress_bar.update(time_diff)\n                self._last_elapsed_seconds = elapsed_seconds\n\n            else:\n                assert False\n\n    def close(self) -> None:\n        \"\"\"Close progress bars.\"\"\"\n\n        if self._is_valid:\n            self._progress_bar.close()\n            assert _tqdm_handler is not None\n            optuna_logging._get_library_root_logger().removeHandler(_tqdm_handler)\n            optuna_logging.enable_default_handler()\n", "path": "optuna/progress_bar.py"}]}