Repository: zulip/zulip-terminal

Issue:
add option to disable debug.log
Currently, `debug.log` is created wherever the current directory is, and if there are no errors, it is a 0B empty file, even if zulip-term is launched without the `-d` flag.


I would like the creation of `debug.log` to be tied to that `-d` flag, as it gets messy and annoying after a while, deleting that file again and again, i.e. if the debug flag is passed then use debug.log, else don't create it.

If not that, then at least an option to disable creating that file.

Discussion:
neiljp: @zee-bit Thanks for the feedback!
@preetmishra Thanks for the suggestion to output the debug.log info when starting 👍 

I've adjusted for that and merging now - let's get to using this! :)

Patch:
diff --git a/README.md b/README.md
index 9da2352..b70ef96 100644
--- a/README.md
+++ b/README.md
@@ -321,17 +321,15 @@ For additional help with pytest options see `pytest -h`, or check out the [full
 
 #### Output using `print`
 
-The stdout for zulip-terminal is redirected to `./debug.log` by default.
+The stdout (standard output) for zulip-terminal is redirected to `./debug.log` if debugging is enabled at run-time using `-d` or `--debug`.
 
-If you want to check the value of a variable, or perhaps indicate reaching a certain point in the code, you can simply write
+This means that if you want to check the value of a variable, or perhaps indicate reaching a certain point in the code, you can simply use `print()`, eg.
 ```python3
-print(variable, flush=True)
+print(f"Just about to do something with {variable}")
 ```
-and the value of the variable will be printed to `./debug.log`.
+and when running with a debugging option, the string will be printed to `./debug.log`.
 
-We suggest the `flush=True` to ensure it prints straight away.
-
-If you have a bash-like terminal, you can run something like `tail -f debug.log` in another terminal, to see the output from `print` as it happens.
+With a bash-like terminal, you can run something like `tail -f debug.log` in another terminal, to see the output from `print` as it happens.
 
 #### Interactive debugging using pudb & telnet
 
diff --git a/zulipterminal/cli/run.py b/zulipterminal/cli/run.py
index a705303..5176cff 100755
--- a/zulipterminal/cli/run.py
+++ b/zulipterminal/cli/run.py
@@ -343,14 +343,17 @@ def main(options: Optional[List[str]] = None) -> None:
     set_encoding("utf-8")
 
     if args.debug:
+        debug_path: Optional[str] = "debug.log"
+        assert isinstance(debug_path, str)
         print(
-            "NOTE: Debug mode enabled; API calls being logged to {}.".format(
-                in_color("blue", API_CALL_LOG_FILENAME)
-            )
+            "NOTE: Debug mode enabled:"
+            f"\n  API calls will be logged to {in_color('blue', API_CALL_LOG_FILENAME)}"
+            f"\n  Standard output being logged to {in_color('blue', debug_path)}"
         )
         requests_logfile_handler = logging.FileHandler(API_CALL_LOG_FILENAME)
         requests_logger.addHandler(requests_logfile_handler)
     else:
+        debug_path = None
         requests_logger.addHandler(logging.NullHandler())
 
     if args.profile:
@@ -494,13 +497,14 @@ def main(options: Optional[List[str]] = None) -> None:
         theme_data = generate_theme(theme_to_use[0], color_depth)
 
         Controller(
-            zuliprc_path,
-            maximum_footlinks,
-            theme_to_use[0],
-            theme_data,
-            color_depth,
-            args.explore,
+            config_file=zuliprc_path,
+            maximum_footlinks=maximum_footlinks,
+            theme_name=theme_to_use[0],
+            theme=theme_data,
+            color_depth=color_depth,
+            in_explore_mode=args.explore,
             **boolean_settings,
+            debug_path=debug_path,
         ).main()
     except ServerConnectionFailure as e:
         # Acts as separator between logs
diff --git a/zulipterminal/core.py b/zulipterminal/core.py
index 970a2c8..d24f893 100644
--- a/zulipterminal/core.py
+++ b/zulipterminal/core.py
@@ -52,11 +52,13 @@ class Controller:
 
     def __init__(
         self,
+        *,
         config_file: str,
         maximum_footlinks: int,
         theme_name: str,
         theme: ThemeSpec,
         color_depth: int,
+        debug_path: Optional[str],
         in_explore_mode: bool,
         autohide: bool,
         notify: bool,
@@ -69,6 +71,8 @@ class Controller:
         self.notify_enabled = notify
         self.maximum_footlinks = maximum_footlinks
 
+        self.debug_path = debug_path
+
         self._editor: Optional[Any] = None
 
         self.active_conversation_info: Dict[str, Any] = {}
@@ -150,12 +154,18 @@ class Controller:
 
         self.capture_stdout()
 
-    def capture_stdout(self, path: str = "debug.log") -> None:
+    def capture_stdout(self) -> None:
         if hasattr(self, "_stdout"):
             return
 
         self._stdout = sys.stdout
-        sys.stdout = open(path, "a")
+
+        if self.debug_path is not None:
+            # buffering=1 avoids need for flush=True with print() debugging
+            sys.stdout = open(self.debug_path, "a", buffering=1)
+        else:
+            # Redirect stdout (print does nothing)
+            sys.stdout = open(os.devnull, "a")
 
     def restore_stdout(self) -> None:
         if not hasattr(self, "_stdout"):


Test patch:
diff --git a/tests/core/test_core.py b/tests/core/test_core.py
index 5092222..d5c68f3 100644
--- a/tests/core/test_core.py
+++ b/tests/core/test_core.py
@@ -50,14 +50,17 @@ class TestController:
         self.notify_enabled = False
         self.maximum_footlinks = 3
         result = Controller(
-            self.config_file,
-            self.maximum_footlinks,
-            self.theme_name,
-            self.theme,
-            256,
-            self.in_explore_mode,
-            self.autohide,
-            self.notify_enabled,
+            config_file=self.config_file,
+            maximum_footlinks=self.maximum_footlinks,
+            theme_name=self.theme_name,
+            theme=self.theme,
+            color_depth=256,
+            in_explore_mode=self.in_explore_mode,
+            debug_path=None,
+            **dict(
+                autohide=self.autohide,
+                notify=self.notify_enabled,
+            ),
         )
         result.view.message_view = mocker.Mock()  # set in View.__init__
         result.model.server_url = SERVER_URL