Integrate colorama for colored output.

This commit is contained in:
Dan Helfman 2019-05-13 19:50:36 +00:00 committed by Gitea
commit 31dc903877
18 changed files with 142 additions and 18 deletions

View file

@ -3,13 +3,14 @@ import os
import subprocess import subprocess
from borgmatic.borg import extract from borgmatic.borg import extract
from borgmatic.logger import get_logger
DEFAULT_CHECKS = ('repository', 'archives') DEFAULT_CHECKS = ('repository', 'archives')
DEFAULT_PREFIX = '{hostname}-' DEFAULT_PREFIX = '{hostname}-'
logger = logging.getLogger(__name__) logger = get_logger(__name__)
def _parse_checks(consistency_config): def _parse_checks(consistency_config):

View file

@ -5,9 +5,10 @@ import os
import tempfile import tempfile
from borgmatic.borg.execute import execute_command from borgmatic.borg.execute import execute_command
from borgmatic.logger import get_logger
logger = logging.getLogger(__name__) logger = get_logger(__name__)
def _expand_directory(directory): def _expand_directory(directory):

View file

@ -1,8 +1,9 @@
import logging
import subprocess import subprocess
from borgmatic.logger import get_logger
logger = logging.getLogger(__name__)
logger = get_logger(__name__)
def execute_command(full_command, capture_output=False): def execute_command(full_command, capture_output=False):

View file

@ -2,8 +2,10 @@ import logging
import sys import sys
import subprocess import subprocess
from borgmatic.logger import get_logger
logger = logging.getLogger(__name__)
logger = get_logger(__name__)
def extract_last_archive_dry_run(repository, lock_wait=None, local_path='borg', remote_path=None): def extract_last_archive_dry_run(repository, lock_wait=None, local_path='borg', remote_path=None):

View file

@ -1,9 +1,10 @@
import logging import logging
from borgmatic.borg.execute import execute_command from borgmatic.borg.execute import execute_command
from borgmatic.logger import get_logger
logger = logging.getLogger(__name__) logger = get_logger(__name__)
def display_archives_info( def display_archives_info(

View file

@ -1,8 +1,9 @@
import logging import logging
import subprocess import subprocess
from borgmatic.logger import get_logger
logger = logging.getLogger(__name__) logger = get_logger(__name__)
def initialize_repository( def initialize_repository(

View file

@ -1,9 +1,10 @@
import logging import logging
from borgmatic.borg.execute import execute_command from borgmatic.borg.execute import execute_command
from borgmatic.logger import get_logger
logger = logging.getLogger(__name__) logger = get_logger(__name__)
def list_archives( def list_archives(

View file

@ -1,8 +1,10 @@
import logging import logging
import subprocess import subprocess
from borgmatic.logger import get_logger
logger = logging.getLogger(__name__)
logger = get_logger(__name__)
def _make_prune_flags(retention_config): def _make_prune_flags(retention_config):

View file

@ -1,5 +1,6 @@
from argparse import ArgumentParser from argparse import ArgumentParser
import collections import collections
import colorama
import json import json
import logging import logging
import os import os
@ -20,12 +21,12 @@ from borgmatic.borg import (
) )
from borgmatic.commands import hook from borgmatic.commands import hook
from borgmatic.config import checks, collect, convert, validate from borgmatic.config import checks, collect, convert, validate
from borgmatic.logger import should_do_markup, get_logger
from borgmatic.signals import configure_signals from borgmatic.signals import configure_signals
from borgmatic.verbosity import verbosity_to_log_level from borgmatic.verbosity import verbosity_to_log_level
logger = logging.getLogger(__name__) logger = get_logger(__name__)
LEGACY_CONFIG_PATH = '/etc/borgmatic/config' LEGACY_CONFIG_PATH = '/etc/borgmatic/config'
@ -169,6 +170,9 @@ def parse_arguments(*arguments):
action='store_true', action='store_true',
help='Go through the motions, but do not actually write to any repositories', help='Go through the motions, but do not actually write to any repositories',
) )
common_group.add_argument(
'-nc', '--no-color', dest='no_color', action='store_true', help='Disable colored output'
)
common_group.add_argument( common_group.add_argument(
'-v', '-v',
'--verbosity', '--verbosity',
@ -472,6 +476,8 @@ def main(): # pragma: no cover
logger.critical(error) logger.critical(error)
exit_with_help_link() exit_with_help_link()
colorama.init(autoreset=True, strip=not should_do_markup(args.no_color))
logging.basicConfig(level=verbosity_to_log_level(args.verbosity), format='%(message)s') logging.basicConfig(level=verbosity_to_log_level(args.verbosity), format='%(message)s')
if args.version: if args.version:

View file

@ -1,8 +1,9 @@
import logging
import subprocess import subprocess
from borgmatic.logger import get_logger
logger = logging.getLogger(__name__)
logger = get_logger(__name__)
def execute_hook(commands, config_filename, description, dry_run): def execute_hook(commands, config_filename, description, dry_run):

View file

@ -3,8 +3,9 @@ import sys
import logging import logging
from borgmatic.config import collect, validate from borgmatic.config import collect, validate
from borgmatic.logger import get_logger
logger = logging.getLogger(__name__) logger = get_logger(__name__)
def parse_arguments(*arguments): def parse_arguments(*arguments):

View file

@ -1,10 +1,11 @@
import os import os
import logging
import ruamel.yaml import ruamel.yaml
from borgmatic.logger import get_logger
logger = logging.getLogger(__name__)
logger = get_logger(__name__)
def load_configuration(filename): def load_configuration(filename):

View file

@ -6,9 +6,10 @@ import pykwalify.errors
import ruamel.yaml import ruamel.yaml
from borgmatic.config import load from borgmatic.config import load
from borgmatic.logger import get_logger
logger = logging.getLogger(__name__) logger = get_logger(__name__)
def schema_filename(): def schema_filename():

75
borgmatic/logger.py Normal file
View file

@ -0,0 +1,75 @@
import logging
import os
import sys
import colorama
def to_bool(arg):
'''
Return a boolean value based on `arg`.
'''
if arg is None or isinstance(arg, bool):
return arg
if isinstance(arg, str):
arg = arg.lower()
if arg in ('yes', 'on', '1', 'true', 1):
return True
return False
def should_do_markup(no_colour):
'''
Determine if we should enable colorama marking up.
'''
if no_colour:
return False
py_colors = os.environ.get('PY_COLORS', None)
if py_colors is not None:
return to_bool(py_colors)
return sys.stdout.isatty() and os.environ.get('TERM') != 'dumb'
class BorgmaticLogger(logging.Logger):
def warn(self, msg, *args, **kwargs):
return super(BorgmaticLogger, self).warn(
color_text(colorama.Fore.YELLOW, msg), *args, **kwargs
)
def info(self, msg, *args, **kwargs):
return super(BorgmaticLogger, self).info(
color_text(colorama.Fore.GREEN, msg), *args, **kwargs
)
def debug(self, msg, *args, **kwargs):
return super(BorgmaticLogger, self).debug(
color_text(colorama.Fore.CYAN, msg), *args, **kwargs
)
def critical(self, msg, *args, **kwargs):
return super(BorgmaticLogger, self).critical(
color_text(colorama.Fore.RED, msg), *args, **kwargs
)
def get_logger(name=None):
'''
Build a logger with the given name.
'''
logging.setLoggerClass(BorgmaticLogger)
logger = logging.getLogger(name)
logger.propagate = False
return logger
def color_text(color, msg):
'''
Give colored text.
'''
return '{}{}{}'.format(color, msg, colorama.Style.RESET_ALL)

View file

@ -187,6 +187,12 @@ sudo systemctl start borgmatic.timer
Feel free to modify the timer file based on how frequently you'd like Feel free to modify the timer file based on how frequently you'd like
borgmatic to run. borgmatic to run.
## Colored Output
Borgmatic uses [colorama](https://pypi.org/project/colorama/) to produce
colored terminal output by default. It is disabled when a non-interactive
terminal is detected (like a cron job). Otherwise, it can be disabled by
passing `--no-color` or by setting the environment variable `PY_COLORS=False`.
## Troubleshooting ## Troubleshooting

View file

@ -30,6 +30,11 @@ setup(
] ]
}, },
obsoletes=['atticmatic'], obsoletes=['atticmatic'],
install_requires=('pykwalify>=1.6.0,<14.06', 'ruamel.yaml>0.15.0,<0.16.0', 'setuptools'), install_requires=(
'pykwalify>=1.6.0,<14.06',
'ruamel.yaml>0.15.0,<0.16.0',
'setuptools',
'colorama>=0.4.1,<0.5',
),
include_package_data=True, include_package_data=True,
) )

View file

@ -3,6 +3,7 @@ atomicwrites==1.2.1
attrs==18.2.0 attrs==18.2.0
black==18.9b0; python_version >= '3.6' black==18.9b0; python_version >= '3.6'
Click==7.0 Click==7.0
colorama==0.4.1
coverage==4.5.1 coverage==4.5.1
docopt==0.6.2 docopt==0.6.2
flake8==3.5.0 flake8==3.5.0

17
tests/unit/test_logger.py Normal file
View file

@ -0,0 +1,17 @@
import pytest
from borgmatic.logger import to_bool
@pytest.mark.parametrize('bool_val', (True, 'yes', 'on', '1', 'true', 'True', 1))
def test_logger_to_bool_is_true(bool_val):
assert to_bool(bool_val)
@pytest.mark.parametrize('bool_val', (False, 'no', 'off', '0', 'false', 'False', 0))
def test_logger_to_bool_is_false(bool_val):
assert not to_bool(bool_val)
def test_logger_to_bool_returns_none():
assert to_bool(None) is None