diff --git a/deluge/log.py b/deluge/log.py index d8e98a458..d58600bea 100644 --- a/deluge/log.py +++ b/deluge/log.py @@ -107,7 +107,8 @@ levels = { } -def setup_logger(level="error", filename=None, filemode="w", logrotate=None, twisted_observer=True): +def setup_logger(level="error", filename=None, filemode="w", logrotate=None, + output_stream=sys.stdout, twisted_observer=True): """ Sets up the basic logger and if `:param:filename` is set, then it will log to that file instead of stdout. @@ -119,6 +120,7 @@ def setup_logger(level="error", filename=None, filemode="w", logrotate=None, twi filemode (str): The filemode to use when opening the log file logrotate (int, optional): The size of the logfile in bytes when enabling log rotation (Default is None meaning disabled) + output_stream (file descriptor): File descriptor to log to if not logging to file twisted_observer (bool): Whether to setup the custom twisted logging observer. """ if logging.getLoggerClass() is not Logging: @@ -141,7 +143,7 @@ def setup_logger(level="error", filename=None, filemode="w", logrotate=None, twi handler_cls = getattr(logging.handlers, "WatchedFileHandler", logging.FileHandler) handler = handler_cls(filename, mode=filemode, encoding="utf-8") else: - handler = logging.StreamHandler(stream=sys.stdout) + handler = logging.StreamHandler(stream=output_stream) handler.setLevel(level) diff --git a/deluge/ui/baseargparser.py b/deluge/ui/baseargparser.py index 2693d3dd7..4684f1de8 100644 --- a/deluge/ui/baseargparser.py +++ b/deluge/ui/baseargparser.py @@ -154,8 +154,14 @@ class BaseArgParser(argparse.ArgumentParser): def __init__(self, *args, **kwargs): if "formatter_class" not in kwargs: kwargs["formatter_class"] = lambda prog: DelugeTextHelpFormatter(prog, max_help_position=33, width=90) + kwargs["add_help"] = kwargs.get("add_help", False) common_help = kwargs.pop("common_help", True) + self.log_stream = sys.stdout + if "log_stream" in kwargs: + self.log_stream = kwargs["log_stream"] + del kwargs["log_stream"] + super(BaseArgParser, self).__init__(*args, **kwargs) self.common_setup = False @@ -229,6 +235,7 @@ class BaseArgParser(argparse.ArgumentParser): """ if not self.common_setup: self.common_setup = True + # Setup the logger if options.quiet: options.loglevel = "none" @@ -243,7 +250,7 @@ class BaseArgParser(argparse.ArgumentParser): # Setup the logger deluge.log.setup_logger(level=options.loglevel, filename=options.logfile, filemode=logfile_mode, - logrotate=logrotate) + logrotate=logrotate, output_stream=self.log_stream) if options.config: if not set_config_dir(options.config): diff --git a/deluge/ui/console/console.py b/deluge/ui/console/console.py index a58514792..7d81e7696 100644 --- a/deluge/ui/console/console.py +++ b/deluge/ui/console/console.py @@ -11,6 +11,7 @@ from __future__ import print_function import logging import os +import sys import deluge.common from deluge.ui.baseargparser import BaseArgParser, DelugeTextHelpFormatter @@ -49,12 +50,22 @@ def load_commands(command_dir): return {} +class LogStream(object): + out = sys.stdout + + def write(self, data): + self.out.write(data) + + def flush(self): + self.out.flush() + + class Console(UI): cmd_description = """Console or command-line user interface""" def __init__(self, *args, **kwargs): - super(Console, self).__init__("console", *args, **kwargs) + super(Console, self).__init__("console", *args, log_stream=LogStream(), **kwargs) group = self.parser.add_argument_group(_("Console Options"), "These daemon connect options will be " "used for commands, or if console ui autoconnect is enabled.") @@ -94,7 +105,7 @@ class Console(UI): def run(options): try: - c = ConsoleUI(self.options, self.console_cmds) + c = ConsoleUI(self.options, self.console_cmds, self.parser.log_stream) return c.start_ui() except Exception as ex: log.exception(ex) diff --git a/deluge/ui/console/main.py b/deluge/ui/console/main.py index a8ba152ee..efef43e90 100644 --- a/deluge/ui/console/main.py +++ b/deluge/ui/console/main.py @@ -217,9 +217,11 @@ class BaseCommand(object): class ConsoleUI(component.Component): - def __init__(self, options=None, cmds=None): + def __init__(self, options, cmds, log_stream): component.Component.__init__(self, "ConsoleUI", 2) self.options = options + self.log_stream = log_stream + # keep track of events for the log view self.events = [] self.statusbars = None @@ -274,6 +276,20 @@ Please use commands from the command line, e.g.:\n deluge-console.exe "add -p c:\\mytorrents c:\\new.torrent" """) else: + class ConsoleLog(object): + def write(self, data): + pass + + def flush(self): + pass + + self.log_stream.out = ConsoleLog() + + # Set Esc key delay to 0 to avoid a very annoying delay + # due to curses waiting in case of other key are pressed + # after ESC is pressed + os.environ.setdefault('ESCDELAY', '0') + # We use the curses.wrapper function to prevent the console from getting # messed up if an uncaught exception is experienced. import curses.wrapper