From d62ce5f8a4c60205083ce345498cf5eadb408a93 Mon Sep 17 00:00:00 2001 From: Ruslan Kuprieiev Date: Sun, 21 May 2017 03:33:13 +0300 Subject: [PATCH 1/4] dvc: fix usage msg --- dvc/runtime.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dvc/runtime.py b/dvc/runtime.py index 92e9648dd..06cb18151 100644 --- a/dvc/runtime.py +++ b/dvc/runtime.py @@ -34,6 +34,9 @@ class Runtime(object): args = sys.argv[args_start_loc:] + # To make argparse print "usage: dvc cmd" instead of "usage: dvc" + sys.argv[0] = sys.argv[0] + " " + sys.argv[1] + instance = cmd_class(Settings(args, runtime_git, runtime_config)) sys.exit(instance.run()) except DvcException as e: From 96c25799f5ab94136a1c8686afbee7d3d90a3008 Mon Sep 17 00:00:00 2001 From: Ruslan Kuprieiev Date: Mon, 22 May 2017 02:24:24 +0300 Subject: [PATCH 2/4] logger: use standard logging python module There is no need to keep our own implementation, as we have more versatile cross-platform standard module for it. For now just replacing Logger class guts with redirects to 'logging' module, and writing everything into single logging instance. --- dvc/logger.py | 67 +++++++++++++++++++-------------------------------- 1 file changed, 25 insertions(+), 42 deletions(-) diff --git a/dvc/logger.py b/dvc/logger.py index 4d7b9ae20..3fc76a626 100644 --- a/dvc/logger.py +++ b/dvc/logger.py @@ -1,52 +1,35 @@ -class Logger(object): - DEFAULT_LEVEL = 2 +import logging - LEVEL = DEFAULT_LEVEL +class Logger(object): + DEFAULT_LEVEL = logging.INFO LEVEL_MAP = { - 'debug': 1, - 'info': 2, - 'warn': 3, - 'error': 4 + 'debug': logging.DEBUG, + 'info': logging.INFO, + 'warn': logging.WARNING, + 'error': logging.ERROR } + logging.basicConfig(stream=sys.stdout, format='%(message)s', level=DEFAULT_LEVEL) + + _logger = logging.getLogger('dvc') + @staticmethod def set_level(level): - Logger.LEVEL = Logger.LEVEL_MAP.get(level.lower(), 'debug') - - @staticmethod - def is_debug(): - return Logger.LEVEL <= 1 - - @staticmethod - def is_info(): - return Logger.LEVEL <= 2 - - @staticmethod - def is_warn(): - return Logger.LEVEL <= 3 - - @staticmethod - def is_error(): - return Logger.LEVEL <= 4 - - @staticmethod - def debug(msg): - if Logger.is_debug(): - print(u'Debug. {}'.format(msg)) - - @staticmethod - def info(msg): - if Logger.is_info(): - #print(u'Info. {}'.format(msg)) - print(msg) - - @staticmethod - def warn(msg): - if Logger.is_warn(): - print(u'Warning. {}'.format(msg)) + Logger._logger.setLevel(Logger.LEVEL_MAP.get(level.lower(), 'debug')) @staticmethod def error(msg): - if Logger.is_error(): - print(u'Error. {}'.format(msg)) + return Logger._logger.error(msg) + + @staticmethod + def warn(msg): + return Logger._logger.warn(msg) + + @staticmethod + def debug(msg): + return Logger._logger.debug(msg) + + @staticmethod + def info(msg): + return Logger._logger.info(msg) From 57a30764b716fba102e39466d9120bad7238d8ce Mon Sep 17 00:00:00 2001 From: Ruslan Kuprieiev Date: Mon, 22 May 2017 02:57:54 +0300 Subject: [PATCH 3/4] dvc: add -v|--verbose and -q|-quiet These are cmdline shortcuts to change dvc's verbosity without fiddling around with loglevel in dvc.conf. Both are added and handled as a common options for all dvc commands in base cmd class. --- dvc/command/base.py | 13 +++++++++++++ dvc/logger.py | 8 ++++++++ 2 files changed, 21 insertions(+) diff --git a/dvc/command/base.py b/dvc/command/base.py index 1cd76bd9f..c58a72b17 100644 --- a/dvc/command/base.py +++ b/dvc/command/base.py @@ -41,10 +41,13 @@ class CmdBase(object): self._settings = settings parser = argparse.ArgumentParser() + self.define_common_args(parser) self.define_args(parser) self._parsed_args, self._command_args = parser.parse_known_args(args=self.args) + self.process_common_args() + @property def settings(self): return self._settings @@ -88,6 +91,16 @@ class CmdBase(object): help='Lock data item - disable reproduction. ' + 'It can be enabled by `dvc lock` command or by forcing reproduction.') + def define_common_args(self, parser): + parser.add_argument('--quiet', '-q', action='store_true', default=False, help='Be quiet.') + parser.add_argument('--verbose', '-v', action='store_true', default=False, help='Be verbose.') + + def process_common_args(self): + if self._parsed_args.quiet and not self._parsed_args.verbose: + Logger.be_quiet() + elif not self._parsed_args.quiet and self._parsed_args.verbose: + Logger.be_verbose() + @property def no_git_actions(self): return self.parsed_args.no_git_actions diff --git a/dvc/logger.py b/dvc/logger.py index 3fc76a626..e630a685a 100644 --- a/dvc/logger.py +++ b/dvc/logger.py @@ -18,6 +18,14 @@ class Logger(object): def set_level(level): Logger._logger.setLevel(Logger.LEVEL_MAP.get(level.lower(), 'debug')) + @staticmethod + def be_quiet(): + Logger._logger.setLevel(logging.CRITICAL) + + @staticmethod + def be_verbose(): + Logger._logger.setLevel(logging.DEBUG) + @staticmethod def error(msg): return Logger._logger.error(msg) From e02437ed97656fe241bd44f2d5ef864c6830df7a Mon Sep 17 00:00:00 2001 From: Ruslan Kuprieiev Date: Mon, 22 May 2017 04:09:39 +0300 Subject: [PATCH 4/4] dvc: logger: use colorama to colorize output Colors help readability, especially in verbose mode. Current color map: Debug: Blue Info: White Warning: Yellow Error: Red --- dvc/logger.py | 28 ++++++++++++++++++++++++---- requirements.txt | 1 + setup.py | 1 + 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/dvc/logger.py b/dvc/logger.py index e630a685a..1b36c7a0d 100644 --- a/dvc/logger.py +++ b/dvc/logger.py @@ -1,5 +1,8 @@ +import sys import logging +import colorama + class Logger(object): DEFAULT_LEVEL = logging.INFO @@ -10,6 +13,12 @@ class Logger(object): 'error': logging.ERROR } + COLOR_MAP = { + 'debug': colorama.Fore.BLUE, + 'warn': colorama.Fore.YELLOW, + 'error': colorama.Fore.RED + } + logging.basicConfig(stream=sys.stdout, format='%(message)s', level=DEFAULT_LEVEL) _logger = logging.getLogger('dvc') @@ -26,18 +35,29 @@ class Logger(object): def be_verbose(): Logger._logger.setLevel(logging.DEBUG) + @staticmethod + def colorize(msg, typ): + header = '' + footer = '' + + if sys.stdout.isatty(): + header = Logger.COLOR_MAP.get(typ.lower(), '') + footer = colorama.Style.RESET_ALL + + return u'{}{}{}'.format(header, msg, footer) + @staticmethod def error(msg): - return Logger._logger.error(msg) + return Logger._logger.error(Logger.colorize(msg, 'error')) @staticmethod def warn(msg): - return Logger._logger.warn(msg) + return Logger._logger.warn(Logger.colorize(msg, 'warn')) @staticmethod def debug(msg): - return Logger._logger.debug(msg) + return Logger._logger.debug(Logger.colorize(msg, 'debug')) @staticmethod def info(msg): - return Logger._logger.info(msg) + return Logger._logger.info(Logger.colorize(msg, 'info')) diff --git a/requirements.txt b/requirements.txt index fac3b1245..a772e726c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -84,3 +84,4 @@ simplegeneric==0.8.1 six==1.10.0 traitlets==4.3.2 wcwidth==0.1.7 +colorama diff --git a/setup.py b/setup.py index 8e0bc1caa..f58e35eaa 100644 --- a/setup.py +++ b/setup.py @@ -90,6 +90,7 @@ install_requires = [ 'six==1.10.0', 'traitlets==4.3.2', 'wcwidth==0.1.7', + 'colorama', ] if platform.system() == 'Darwin':