提交 f2ca8094 编写于 作者: L Lukáš Doktor

avocado: Use output.LOG_{UI,JOB} in Avocado

Currently we hardcode the "avocado.app" and "avocado.test" loggers
everywhere in Avocado, let's use the newly defined
`avocado.core.output.LOG_{UI,JOB}` variables everywhere in Avocado
except of `avocado.utils`, which shouldn't have used this interface in
the first place and will be subject of change in the future.
Signed-off-by: NLukáš Doktor <ldoktor@redhat.com>
上级 14f4152e
...@@ -25,7 +25,6 @@ The general reasoning to find paths is: ...@@ -25,7 +25,6 @@ The general reasoning to find paths is:
* The next best location is the default system wide one. * The next best location is the default system wide one.
* The next best location is the default user specific one. * The next best location is the default user specific one.
""" """
import logging
import os import os
import sys import sys
import shutil import shutil
...@@ -34,6 +33,7 @@ import tempfile ...@@ -34,6 +33,7 @@ import tempfile
from . import job_id from . import job_id
from . import settings from . import settings
from .output import LOG_JOB
from ..utils import path as utils_path from ..utils import path as utils_path
from ..utils.data_structures import Borg from ..utils.data_structures import Borg
...@@ -53,8 +53,6 @@ USER_TEST_DIR = os.path.join(USER_BASE_DIR, 'tests') ...@@ -53,8 +53,6 @@ USER_TEST_DIR = os.path.join(USER_BASE_DIR, 'tests')
USER_DATA_DIR = os.path.join(USER_BASE_DIR, 'data') USER_DATA_DIR = os.path.join(USER_BASE_DIR, 'data')
USER_LOG_DIR = os.path.join(USER_BASE_DIR, 'job-results') USER_LOG_DIR = os.path.join(USER_BASE_DIR, 'job-results')
LOG = logging.getLogger('avocado.test')
def _get_settings_dir(dir_name): def _get_settings_dir(dir_name):
""" """
...@@ -206,8 +204,8 @@ class _TmpDirTracker(Borg): ...@@ -206,8 +204,8 @@ class _TmpDirTracker(Borg):
self.tmp_dir = tempfile.mkdtemp(prefix='avocado_', self.tmp_dir = tempfile.mkdtemp(prefix='avocado_',
dir=self.basedir) dir=self.basedir)
elif basedir is not None and basedir != self.basedir: elif basedir is not None and basedir != self.basedir:
LOG.error("The tmp_dir was already created. The new basedir " LOG_JOB.error("The tmp_dir was already created. The new basedir "
"you're trying to provide will have no effect.") "you're trying to provide will have no effect.")
return self.tmp_dir return self.tmp_dir
def unittest_refresh_dir_tracker(self): def unittest_refresh_dir_tracker(self):
......
...@@ -15,12 +15,12 @@ ...@@ -15,12 +15,12 @@
"""Extensions/plugins dispatchers.""" """Extensions/plugins dispatchers."""
import copy import copy
import logging
import sys import sys
from stevedore import EnabledExtensionManager from stevedore import EnabledExtensionManager
from .settings import settings from .settings import settings
from .output import LOG_UI
from ..utils import stacktrace from ..utils import stacktrace
...@@ -183,7 +183,6 @@ class ResultEventsDispatcher(Dispatcher): ...@@ -183,7 +183,6 @@ class ResultEventsDispatcher(Dispatcher):
super(ResultEventsDispatcher, self).__init__( super(ResultEventsDispatcher, self).__init__(
'avocado.plugins.result_events', 'avocado.plugins.result_events',
invoke_kwds={'args': args}) invoke_kwds={'args': args})
self.log = logging.getLogger("avocado.app")
def map_method(self, method_name, *args): def map_method(self, method_name, *args):
for ext in self.extensions: for ext in self.extensions:
...@@ -196,8 +195,8 @@ class ResultEventsDispatcher(Dispatcher): ...@@ -196,8 +195,8 @@ class ResultEventsDispatcher(Dispatcher):
except KeyboardInterrupt: except KeyboardInterrupt:
raise raise
except: except:
self.log.error('Error running method "%s" of plugin "%s": %s', LOG_UI.error('Error running method "%s" of plugin "%s": %s',
method_name, ext.name, sys.exc_info()[1]) method_name, ext.name, sys.exc_info()[1])
class VarianterDispatcher(Dispatcher): class VarianterDispatcher(Dispatcher):
...@@ -244,9 +243,8 @@ class VarianterDispatcher(Dispatcher): ...@@ -244,9 +243,8 @@ class VarianterDispatcher(Dispatcher):
raise raise
except: # catch any exception pylint: disable=W0702 except: # catch any exception pylint: disable=W0702
stacktrace.log_exc_info(sys.exc_info(), logger='avocado.debug') stacktrace.log_exc_info(sys.exc_info(), logger='avocado.debug')
log = logging.getLogger("avocado.app") LOG_UI.error('Error running method "%s" of plugin "%s": %s',
log.error('Error running method "%s" of plugin "%s": %s', method_name, ext.name, sys.exc_info()[1])
method_name, ext.name, sys.exc_info()[1])
return ret return ret
def map_method(self, method_name, *args, **kwargs): def map_method(self, method_name, *args, **kwargs):
......
...@@ -49,12 +49,12 @@ from ..utils import runtime ...@@ -49,12 +49,12 @@ from ..utils import runtime
from ..utils import stacktrace from ..utils import stacktrace
from ..utils import data_structures from ..utils import data_structures
from ..utils import process from ..utils import process
from .output import LOG_JOB
from .output import LOG_UI
_NEW_ISSUE_LINK = 'https://github.com/avocado-framework/avocado/issues/new' _NEW_ISSUE_LINK = 'https://github.com/avocado-framework/avocado/issues/new'
_TEST_LOGGER = logging.getLogger('avocado.test')
class Job(object): class Job(object):
...@@ -75,7 +75,7 @@ class Job(object): ...@@ -75,7 +75,7 @@ class Job(object):
args = argparse.Namespace() args = argparse.Namespace()
self.args = args self.args = args
self.references = getattr(args, "reference", []) self.references = getattr(args, "reference", [])
self.log = logging.getLogger("avocado.app") self.log = LOG_UI
self.standalone = getattr(self.args, 'standalone', False) self.standalone = getattr(self.args, 'standalone', False)
if getattr(self.args, "dry_run", False): # Modify args for dry-run if getattr(self.args, "dry_run", False): # Modify args for dry-run
if not self.args.unique_job_id: if not self.args.unique_job_id:
...@@ -122,7 +122,7 @@ class Job(object): ...@@ -122,7 +122,7 @@ class Job(object):
self.__start_job_logging() self.__start_job_logging()
self.funcatexit = data_structures.CallbackRegister("JobExit %s" self.funcatexit = data_structures.CallbackRegister("JobExit %s"
% self.unique_id, % self.unique_id,
_TEST_LOGGER) LOG_JOB)
self._stdout_stderr = None self._stdout_stderr = None
self.replay_sourcejob = getattr(self.args, 'replay_sourcejob', None) self.replay_sourcejob = getattr(self.args, 'replay_sourcejob', None)
self.exitcode = exit_codes.AVOCADO_ALL_OK self.exitcode = exit_codes.AVOCADO_ALL_OK
...@@ -181,13 +181,13 @@ class Job(object): ...@@ -181,13 +181,13 @@ class Job(object):
# Enable test logger # Enable test logger
fmt = ('%(asctime)s %(module)-16.16s L%(lineno)-.4d %(' fmt = ('%(asctime)s %(module)-16.16s L%(lineno)-.4d %('
'levelname)-5.5s| %(message)s') 'levelname)-5.5s| %(message)s')
test_handler = output.add_log_handler("avocado.test", test_handler = output.add_log_handler(LOG_JOB,
logging.FileHandler, logging.FileHandler,
self.logfile, self.loglevel, fmt) self.logfile, self.loglevel, fmt)
root_logger = logging.getLogger() root_logger = logging.getLogger()
root_logger.addHandler(test_handler) root_logger.addHandler(test_handler)
root_logger.setLevel(self.loglevel) root_logger.setLevel(self.loglevel)
self.__logging_handlers[test_handler] = ["avocado.test", ""] self.__logging_handlers[test_handler] = [LOG_JOB.name, ""]
# Add --store-logging-streams # Add --store-logging-streams
fmt = '%(asctime)s %(levelname)-5.5s| %(message)s' fmt = '%(asctime)s %(levelname)-5.5s| %(message)s'
formatter = logging.Formatter(fmt=fmt, datefmt='%H:%M:%S') formatter = logging.Formatter(fmt=fmt, datefmt='%H:%M:%S')
...@@ -218,13 +218,13 @@ class Job(object): ...@@ -218,13 +218,13 @@ class Job(object):
# Enable std{out,err} but redirect booth to stderr # Enable std{out,err} but redirect booth to stderr
sys.stdout = STD_OUTPUT.stdout sys.stdout = STD_OUTPUT.stdout
sys.stderr = STD_OUTPUT.stdout sys.stderr = STD_OUTPUT.stdout
test_handler = output.add_log_handler("avocado.test", test_handler = output.add_log_handler(LOG_JOB,
logging.StreamHandler, logging.StreamHandler,
STD_OUTPUT.stdout, STD_OUTPUT.stdout,
logging.DEBUG, logging.DEBUG,
fmt="%(message)s") fmt="%(message)s")
root_logger.addHandler(test_handler) root_logger.addHandler(test_handler)
self.__logging_handlers[test_handler] = ["avocado.test", ""] self.__logging_handlers[test_handler] = [LOG_JOB.name, ""]
def __stop_job_logging(self): def __stop_job_logging(self):
if self._stdout_stderr: if self._stdout_stderr:
...@@ -239,8 +239,7 @@ class Job(object): ...@@ -239,8 +239,7 @@ class Job(object):
""" """
def soft_abort(msg): def soft_abort(msg):
""" Only log the problem """ """ Only log the problem """
logging.getLogger("avocado.test").warning("Unable to update the " LOG_JOB.warning("Unable to update the latest link: %s" % msg)
"latest link: %s" % msg)
basedir = os.path.dirname(self.logdir) basedir = os.path.dirname(self.logdir)
basename = os.path.basename(self.logdir) basename = os.path.basename(self.logdir)
proc_latest = os.path.join(basedir, "latest.%s" % os.getpid()) proc_latest = os.path.join(basedir, "latest.%s" % os.getpid())
...@@ -310,23 +309,20 @@ class Job(object): ...@@ -310,23 +309,20 @@ class Job(object):
return suite return suite
def _log_job_id(self): def _log_job_id(self):
job_log = _TEST_LOGGER LOG_JOB.info('Job ID: %s', self.unique_id)
job_log.info('Job ID: %s', self.unique_id)
if self.replay_sourcejob is not None: if self.replay_sourcejob is not None:
job_log.info('Replay of Job ID: %s', self.replay_sourcejob) LOG_JOB.info('Replay of Job ID: %s', self.replay_sourcejob)
job_log.info('') LOG_JOB.info('')
@staticmethod @staticmethod
def _log_cmdline(): def _log_cmdline():
job_log = _TEST_LOGGER
cmdline = " ".join(sys.argv) cmdline = " ".join(sys.argv)
job_log.info("Command line: %s", cmdline) LOG_JOB.info("Command line: %s", cmdline)
job_log.info('') LOG_JOB.info('')
@staticmethod @staticmethod
def _log_avocado_version(): def _log_avocado_version():
job_log = _TEST_LOGGER LOG_JOB.info('Avocado version: %s', version.VERSION)
job_log.info('Avocado version: %s', version.VERSION)
if os.path.exists('.git') and os.path.exists('avocado.spec'): if os.path.exists('.git') and os.path.exists('avocado.spec'):
cmd = "git show --summary --pretty='%H'" cmd = "git show --summary --pretty='%H'"
result = process.run(cmd, ignore_status=True) result = process.run(cmd, ignore_status=True)
...@@ -339,24 +335,23 @@ class Job(object): ...@@ -339,24 +335,23 @@ class Job(object):
# Let's display information only if git is installed # Let's display information only if git is installed
# (commands succeed). # (commands succeed).
if status == 0 and status2 == 0: if status == 0 and status2 == 0:
job_log.info('Avocado git repo info') LOG_JOB.info('Avocado git repo info')
job_log.info("Top commit: %s", top_commit) LOG_JOB.info("Top commit: %s", top_commit)
job_log.info("Branch: %s", branch) LOG_JOB.info("Branch: %s", branch)
job_log.info('') LOG_JOB.info('')
@staticmethod @staticmethod
def _log_avocado_config(): def _log_avocado_config():
job_log = _TEST_LOGGER LOG_JOB.info('Config files read (in order):')
job_log.info('Config files read (in order):')
for cfg_path in settings.config_paths: for cfg_path in settings.config_paths:
job_log.info(cfg_path) LOG_JOB.info(cfg_path)
if settings.config_paths_failed: if settings.config_paths_failed:
job_log.info('Config files failed to read (in order):') LOG_JOB.info('Config files failed to read (in order):')
for cfg_path in settings.config_paths_failed: for cfg_path in settings.config_paths_failed:
job_log.info(cfg_path) LOG_JOB.info(cfg_path)
job_log.info('') LOG_JOB.info('')
job_log.info('Avocado config:') LOG_JOB.info('Avocado config:')
header = ('Section.Key', 'Value') header = ('Section.Key', 'Value')
config_matrix = [] config_matrix = []
for section in settings.config.sections(): for section in settings.config.sections():
...@@ -365,28 +360,26 @@ class Job(object): ...@@ -365,28 +360,26 @@ class Job(object):
config_matrix.append([config_key, value[1]]) config_matrix.append([config_key, value[1]])
for line in astring.iter_tabular_output(config_matrix, header): for line in astring.iter_tabular_output(config_matrix, header):
job_log.info(line) LOG_JOB.info(line)
job_log.info('') LOG_JOB.info('')
def _log_avocado_datadir(self): def _log_avocado_datadir(self):
job_log = _TEST_LOGGER LOG_JOB.info('Avocado Data Directories:')
job_log.info('Avocado Data Directories:') LOG_JOB.info('')
job_log.info('') LOG_JOB.info('base ' + data_dir.get_base_dir())
job_log.info('base ' + data_dir.get_base_dir()) LOG_JOB.info('tests ' + data_dir.get_test_dir())
job_log.info('tests ' + data_dir.get_test_dir()) LOG_JOB.info('data ' + data_dir.get_data_dir())
job_log.info('data ' + data_dir.get_data_dir()) LOG_JOB.info('logs ' + self.logdir)
job_log.info('logs ' + self.logdir) LOG_JOB.info('')
job_log.info('')
def _log_variants(self, variants): def _log_variants(self, variants):
lines = variants.to_str(summary=1, variants=1, use_utf8=False) lines = variants.to_str(summary=1, variants=1, use_utf8=False)
for line in lines.splitlines(): for line in lines.splitlines():
_TEST_LOGGER.info(line) LOG_JOB.info(line)
def _log_tmp_dir(self): def _log_tmp_dir(self):
job_log = _TEST_LOGGER LOG_JOB.info('Temporary dir: %s', data_dir.get_tmp_dir())
job_log.info('Temporary dir: %s', data_dir.get_tmp_dir()) LOG_JOB.info('')
job_log.info('')
def _log_job_debug_info(self, mux): def _log_job_debug_info(self, mux):
""" """
...@@ -410,7 +403,7 @@ class Job(object): ...@@ -410,7 +403,7 @@ class Job(object):
self.test_suite = self._make_test_suite(self.references) self.test_suite = self._make_test_suite(self.references)
self.result.tests_total = len(self.test_suite) self.result.tests_total = len(self.test_suite)
except loader.LoaderError as details: except loader.LoaderError as details:
stacktrace.log_exc_info(sys.exc_info(), 'avocado.app.debug') stacktrace.log_exc_info(sys.exc_info(), LOG_UI.getChild("debug"))
raise exceptions.OptionValidationError(details) raise exceptions.OptionValidationError(details)
if not self.test_suite: if not self.test_suite:
...@@ -458,7 +451,7 @@ class Job(object): ...@@ -458,7 +451,7 @@ class Job(object):
# If it's all good so far, set job status to 'PASS' # If it's all good so far, set job status to 'PASS'
if self.status == 'RUNNING': if self.status == 'RUNNING':
self.status = 'PASS' self.status = 'PASS'
_TEST_LOGGER.info('Test results available in %s', self.logdir) LOG_JOB.info('Test results available in %s', self.logdir)
if summary is None: if summary is None:
self.exitcode |= exit_codes.AVOCADO_JOB_FAIL self.exitcode |= exit_codes.AVOCADO_JOB_FAIL
......
...@@ -33,6 +33,7 @@ from . import safeloader ...@@ -33,6 +33,7 @@ from . import safeloader
from ..utils import path from ..utils import path
from ..utils import stacktrace from ..utils import stacktrace
from .settings import settings from .settings import settings
from .output import LOG_UI
#: Show default tests (for execution) #: Show default tests (for execution)
DEFAULT = False DEFAULT = False
...@@ -246,9 +247,9 @@ class TestLoaderProxy(object): ...@@ -246,9 +247,9 @@ class TestLoaderProxy(object):
# FIXME: Introduce avocado.exceptions logger and use here # FIXME: Introduce avocado.exceptions logger and use here
stacktrace.log_message("Test discovery plugin %s failed: " stacktrace.log_message("Test discovery plugin %s failed: "
"%s" % (plugin, details), "%s" % (plugin, details),
'avocado.app.exceptions') LOG_UI.getChild("exceptions"))
# FIXME: Introduce avocado.traceback logger and use here # FIXME: Introduce avocado.traceback logger and use here
stacktrace.log_exc_info(sys.exc_info(), 'avocado.app.debug') stacktrace.log_exc_info(sys.exc_info(), LOG_UI.getChild("debug"))
tests = [] tests = []
unhandled_references = [] unhandled_references = []
if not references: if not references:
......
...@@ -348,11 +348,11 @@ def early_start(): ...@@ -348,11 +348,11 @@ def early_start():
Replace all outputs with in-memory handlers Replace all outputs with in-memory handlers
""" """
if os.environ.get('AVOCADO_LOG_DEBUG'): if os.environ.get('AVOCADO_LOG_DEBUG'):
add_log_handler("avocado.app.debug", logging.StreamHandler, sys.stdout, add_log_handler(LOG_UI.getChild("debug"), logging.StreamHandler,
logging.DEBUG) sys.stdout, logging.DEBUG)
if os.environ.get('AVOCADO_LOG_EARLY'): if os.environ.get('AVOCADO_LOG_EARLY'):
add_log_handler("", logging.StreamHandler, sys.stdout, logging.DEBUG) add_log_handler("", logging.StreamHandler, sys.stdout, logging.DEBUG)
add_log_handler("avocado.test", logging.StreamHandler, sys.stdout, add_log_handler(LOG_JOB, logging.StreamHandler, sys.stdout,
logging.DEBUG) logging.DEBUG)
else: else:
STD_OUTPUT.fake_outputs() STD_OUTPUT.fake_outputs()
...@@ -392,34 +392,33 @@ def reconfigure(args): ...@@ -392,34 +392,33 @@ def reconfigure(args):
else: else:
STD_OUTPUT.enable_stderr() STD_OUTPUT.enable_stderr()
STD_OUTPUT.print_records() STD_OUTPUT.print_records()
app_logger = logging.getLogger("avocado.app")
if "app" in enabled: if "app" in enabled:
app_handler = ProgressStreamHandler() app_handler = ProgressStreamHandler()
app_handler.setFormatter(logging.Formatter("%(message)s")) app_handler.setFormatter(logging.Formatter("%(message)s"))
app_handler.addFilter(FilterInfoAndLess()) app_handler.addFilter(FilterInfoAndLess())
app_handler.stream = STD_OUTPUT.stdout app_handler.stream = STD_OUTPUT.stdout
app_logger.addHandler(app_handler) LOG_UI.addHandler(app_handler)
app_logger.propagate = False LOG_UI.propagate = False
app_logger.level = logging.DEBUG LOG_UI.level = logging.DEBUG
else: else:
disable_log_handler("avocado.app") disable_log_handler(LOG_UI)
app_err_handler = ProgressStreamHandler() app_err_handler = ProgressStreamHandler()
app_err_handler.setFormatter(logging.Formatter("%(message)s")) app_err_handler.setFormatter(logging.Formatter("%(message)s"))
app_err_handler.addFilter(FilterWarnAndMore()) app_err_handler.addFilter(FilterWarnAndMore())
app_err_handler.stream = STD_OUTPUT.stderr app_err_handler.stream = STD_OUTPUT.stderr
app_logger.addHandler(app_err_handler) LOG_UI.addHandler(app_err_handler)
app_logger.propagate = False LOG_UI.propagate = False
if not os.environ.get("AVOCADO_LOG_EARLY"): if not os.environ.get("AVOCADO_LOG_EARLY"):
logging.getLogger("avocado.test.stdout").propagate = False LOG_JOB.getChild("stdout").propagate = False
logging.getLogger("avocado.test.stderr").propagate = False LOG_JOB.getChild("stderr").propagate = False
if "early" in enabled: if "early" in enabled:
add_log_handler("", logging.StreamHandler, STD_OUTPUT.stdout, add_log_handler("", logging.StreamHandler, STD_OUTPUT.stdout,
logging.DEBUG) logging.DEBUG)
add_log_handler("avocado.test", logging.StreamHandler, add_log_handler(LOG_JOB, logging.StreamHandler,
STD_OUTPUT.stdout, logging.DEBUG) STD_OUTPUT.stdout, logging.DEBUG)
else: else:
disable_log_handler("") disable_log_handler("")
disable_log_handler("avocado.test") disable_log_handler(LOG_JOB)
if "remote" in enabled: if "remote" in enabled:
add_log_handler("avocado.fabric", stream=STD_OUTPUT.stdout, add_log_handler("avocado.fabric", stream=STD_OUTPUT.stdout,
level=logging.DEBUG) level=logging.DEBUG)
...@@ -431,9 +430,9 @@ def reconfigure(args): ...@@ -431,9 +430,9 @@ def reconfigure(args):
# Not enabled by env # Not enabled by env
if not os.environ.get('AVOCADO_LOG_DEBUG'): if not os.environ.get('AVOCADO_LOG_DEBUG'):
if "debug" in enabled: if "debug" in enabled:
add_log_handler("avocado.app.debug", stream=STD_OUTPUT.stdout) add_log_handler(LOG_UI.getChild("debug"), stream=STD_OUTPUT.stdout)
else: else:
disable_log_handler("avocado.app.debug") disable_log_handler(LOG_UI.getChild("debug"))
# Add custom loggers # Add custom loggers
for name in [_ for _ in enabled if _ not in BUILTIN_STREAMS.iterkeys()]: for name in [_ for _ in enabled if _ not in BUILTIN_STREAMS.iterkeys()]:
...@@ -448,8 +447,8 @@ def reconfigure(args): ...@@ -448,8 +447,8 @@ def reconfigure(args):
add_log_handler(name, logging.StreamHandler, STD_OUTPUT.stdout, add_log_handler(name, logging.StreamHandler, STD_OUTPUT.stdout,
level) level)
except ValueError as details: except ValueError as details:
app_logger.error("Failed to set logger for --show %s:%s: %s.", LOG_UI.error("Failed to set logger for --show %s:%s: %s.",
name, level, details) name, level, details)
sys.exit(exit_codes.AVOCADO_FAIL) sys.exit(exit_codes.AVOCADO_FAIL)
# Remove the in-memory handlers # Remove the in-memory handlers
for handler in logging.root.handlers: for handler in logging.root.handlers:
...@@ -576,18 +575,21 @@ def add_log_handler(logger, klass=logging.StreamHandler, stream=sys.stdout, ...@@ -576,18 +575,21 @@ def add_log_handler(logger, klass=logging.StreamHandler, stream=sys.stdout,
:param level: Log level (defaults to `INFO``) :param level: Log level (defaults to `INFO``)
:param fmt: Logging format (defaults to ``%(name)s: %(message)s``) :param fmt: Logging format (defaults to ``%(name)s: %(message)s``)
""" """
if isinstance(logger, basestring):
logger = logging.getLogger(logger)
handler = klass(stream) handler = klass(stream)
handler.setLevel(level) handler.setLevel(level)
if isinstance(fmt, str): if isinstance(fmt, str):
fmt = logging.Formatter(fmt=fmt) fmt = logging.Formatter(fmt=fmt)
handler.setFormatter(fmt) handler.setFormatter(fmt)
logging.getLogger(logger).addHandler(handler) logger.addHandler(handler)
logging.getLogger(logger).propagate = False logger.propagate = False
return handler return handler
def disable_log_handler(logger): def disable_log_handler(logger):
logger = logging.getLogger(logger) if isinstance(logger, basestring):
logger = logging.getLogger(logger)
# Handlers might be reused elsewhere, can't delete them # Handlers might be reused elsewhere, can't delete them
while logger.handlers: while logger.handlers:
logger.handlers.pop() logger.handlers.pop()
...@@ -704,7 +706,6 @@ def log_plugin_failures(failures): ...@@ -704,7 +706,6 @@ def log_plugin_failures(failures):
:class:`avocado.core.dispatcher.Dispatcher` :class:`avocado.core.dispatcher.Dispatcher`
attribute `load_failures` attribute `load_failures`
""" """
log = logging.getLogger("avocado.app")
msg_fmt = 'Failed to load plugin from module "%s": %s' msg_fmt = 'Failed to load plugin from module "%s": %s'
silenced = settings.get_value('plugins', silenced = settings.get_value('plugins',
'skip_broken_plugin_notification', 'skip_broken_plugin_notification',
...@@ -712,5 +713,5 @@ def log_plugin_failures(failures): ...@@ -712,5 +713,5 @@ def log_plugin_failures(failures):
for failure in failures: for failure in failures:
if failure[0].module_name in silenced: if failure[0].module_name in silenced:
continue continue
log.error(msg_fmt, failure[0].module_name, LOG_UI.error(msg_fmt, failure[0].module_name,
failure[1].__repr__()) failure[1].__repr__())
...@@ -17,13 +17,12 @@ Avocado application command line parsing. ...@@ -17,13 +17,12 @@ Avocado application command line parsing.
""" """
import argparse import argparse
import logging
from . import exit_codes from . import exit_codes
from . import varianter from . import varianter
from . import settings from . import settings
from . import tree from . import tree
from .output import BUILTIN_STREAMS, BUILTIN_STREAM_SETS from .output import BUILTIN_STREAMS, BUILTIN_STREAM_SETS, LOG_UI
from .version import VERSION from .version import VERSION
PROG = 'avocado' PROG = 'avocado'
...@@ -37,9 +36,8 @@ class ArgumentParser(argparse.ArgumentParser): ...@@ -37,9 +36,8 @@ class ArgumentParser(argparse.ArgumentParser):
""" """
def error(self, message): def error(self, message):
log = logging.getLogger("avocado.app") LOG_UI.debug(self.format_help())
log.debug(self.format_help()) LOG_UI.error("%s: error: %s", self.prog, message)
log.error("%s: error: %s", self.prog, message)
self.exit(exit_codes.AVOCADO_FAIL) self.exit(exit_codes.AVOCADO_FAIL)
def _get_option_tuples(self, option_string): def _get_option_tuples(self, option_string):
......
...@@ -6,13 +6,9 @@ Module that implements the actions for the CLI App when the job toplevel ...@@ -6,13 +6,9 @@ Module that implements the actions for the CLI App when the job toplevel
command is used command is used
""" """
import logging
from . import base from . import base
from ... import connection from ... import connection
from ....output import LOG_UI
log = logging.getLogger("avocado.app")
@base.action @base.action
...@@ -21,7 +17,7 @@ def status(app): ...@@ -21,7 +17,7 @@ def status(app):
Shows the server status Shows the server status
""" """
data = app.connection.request("version/") data = app.connection.request("version/")
log.info("Server version: %s", data.get('version')) LOG_UI.info("Server version: %s", data.get('version'))
@base.action @base.action
...@@ -33,9 +29,9 @@ def list_brief(app): ...@@ -33,9 +29,9 @@ def list_brief(app):
data = app.connection.get_api_list() data = app.connection.get_api_list()
except connection.UnexpectedHttpStatusCode as e: except connection.UnexpectedHttpStatusCode as e:
if e.received == 403: if e.received == 403:
log.error("Error: Access Forbidden") LOG_UI.error("Error: Access Forbidden")
return False return False
log.info("Available APIs:") LOG_UI.info("Available APIs:")
for name in data: for name in data:
log.info(" * %s", name) LOG_UI.info(" * %s", name)
...@@ -16,13 +16,13 @@ This is the main entry point for the rest client cli application ...@@ -16,13 +16,13 @@ This is the main entry point for the rest client cli application
""" """
import importlib import importlib
import logging
import sys import sys
import types import types
from . import parser from . import parser
from .. import connection from .. import connection
from ... import exit_codes from ... import exit_codes
from ...output import LOG_UI
__all__ = ['App'] __all__ = ['App']
...@@ -48,7 +48,7 @@ class App(object): ...@@ -48,7 +48,7 @@ class App(object):
self.connection = None self.connection = None
self.parser = parser.Parser() self.parser = parser.Parser()
self.parser.add_arguments_on_all_modules() self.parser.add_arguments_on_all_modules()
self.log = logging.getLogger("avocado.app") self.log = LOG_UI
def initialize_connection(self): def initialize_connection(self):
""" """
......
...@@ -36,8 +36,8 @@ from ..utils import runtime ...@@ -36,8 +36,8 @@ from ..utils import runtime
from ..utils import process from ..utils import process
from ..utils import stacktrace from ..utils import stacktrace
TEST_LOG = logging.getLogger("avocado.test") from .output import LOG_UI as APP_LOG
APP_LOG = logging.getLogger("avocado.app") from .output import LOG_JOB as TEST_LOG
#: when test was interrupted (ctrl+c/timeout) #: when test was interrupted (ctrl+c/timeout)
TIMEOUT_TEST_INTERRUPTED = 1 TIMEOUT_TEST_INTERRUPTED = 1
......
...@@ -43,6 +43,7 @@ from ..utils import stacktrace ...@@ -43,6 +43,7 @@ from ..utils import stacktrace
from .decorators import skip from .decorators import skip
from .settings import settings from .settings import settings
from .version import VERSION from .version import VERSION
from .output import LOG_JOB
#: Environment variable used to store the location of a temporary #: Environment variable used to store the location of a temporary
...@@ -216,7 +217,7 @@ class Test(unittest.TestCase): ...@@ -216,7 +217,7 @@ class Test(unittest.TestCase):
self.__sysinfodir = utils_path.init_dir(self.logdir, 'sysinfo') self.__sysinfodir = utils_path.init_dir(self.logdir, 'sysinfo')
self.__sysinfo_logger = sysinfo.SysInfo(basedir=self.__sysinfodir) self.__sysinfo_logger = sysinfo.SysInfo(basedir=self.__sysinfodir)
self.__log = logging.getLogger("avocado.test") self.__log = LOG_JOB
original_log_warn = self.log.warning original_log_warn = self.log.warning
self.__log_warn_used = False self.__log_warn_used = False
self.log.warn = self.log.warning = record_and_warn self.log.warn = self.log.warning = record_and_warn
...@@ -491,22 +492,23 @@ class Test(unittest.TestCase): ...@@ -491,22 +492,23 @@ class Test(unittest.TestCase):
stream_fmt = '%(message)s' stream_fmt = '%(message)s'
stream_formatter = logging.Formatter(fmt=stream_fmt) stream_formatter = logging.Formatter(fmt=stream_fmt)
self._register_log_file_handler( log_test_stdout = LOG_JOB.getChild("stdout")
logging.getLogger("avocado.test.stdout"), log_test_stderr = LOG_JOB.getChild("stderr")
stream_formatter,
self._stdout_file) self._register_log_file_handler(log_test_stdout,
self._register_log_file_handler( stream_formatter,
logging.getLogger("avocado.test.stderr"), self._stdout_file)
stream_formatter, self._register_log_file_handler(log_test_stderr,
self._stderr_file) stream_formatter,
self._stderr_file)
self._register_log_file_handler(logging.getLogger('paramiko'), self._register_log_file_handler(logging.getLogger('paramiko'),
formatter, formatter,
self._ssh_logfile) self._ssh_logfile)
if isinstance(sys.stdout, output.LoggingFile): if isinstance(sys.stdout, output.LoggingFile):
sys.stdout.add_logger(logging.getLogger("avocado.test.stdout")) sys.stdout.add_logger(log_test_stdout)
if isinstance(sys.stderr, output.LoggingFile): if isinstance(sys.stderr, output.LoggingFile):
sys.stderr.add_logger(logging.getLogger("avocado.test.stderr")) sys.stderr.add_logger(log_test_stderr)
def _stop_logging(self): def _stop_logging(self):
""" """
...@@ -514,9 +516,9 @@ class Test(unittest.TestCase): ...@@ -514,9 +516,9 @@ class Test(unittest.TestCase):
""" """
self.log.removeHandler(self.file_handler) self.log.removeHandler(self.file_handler)
if isinstance(sys.stderr, output.LoggingFile): if isinstance(sys.stderr, output.LoggingFile):
sys.stderr.rm_logger(logging.getLogger("avocado.test.stderr")) sys.stderr.rm_logger(LOG_JOB.getChild("stderr"))
if isinstance(sys.stdout, output.LoggingFile): if isinstance(sys.stdout, output.LoggingFile):
sys.stdout.rm_logger(logging.getLogger("avocado.test.stdout")) sys.stdout.rm_logger(LOG_JOB.getChild("stdout"))
for name, handler in self._logging_handlers.iteritems(): for name, handler in self._logging_handlers.iteritems():
logging.getLogger(name).removeHandler(handler) logging.getLogger(name).removeHandler(handler)
...@@ -566,12 +568,12 @@ class Test(unittest.TestCase): ...@@ -566,12 +568,12 @@ class Test(unittest.TestCase):
if skip_test is False: if skip_test is False:
self.setUp() self.setUp()
except (exceptions.TestSetupSkip, exceptions.TestSkipError) as details: except (exceptions.TestSetupSkip, exceptions.TestSkipError) as details:
stacktrace.log_exc_info(sys.exc_info(), logger='avocado.test') stacktrace.log_exc_info(sys.exc_info(), logger=LOG_JOB)
raise exceptions.TestSkipError(details) raise exceptions.TestSkipError(details)
except exceptions.TestCancel as details: except exceptions.TestCancel as details:
cancel_test = details cancel_test = details
except: # Old-style exceptions are not inherited from Exception() except: # Old-style exceptions are not inherited from Exception()
stacktrace.log_exc_info(sys.exc_info(), logger='avocado.test') stacktrace.log_exc_info(sys.exc_info(), logger=LOG_JOB)
details = sys.exc_info()[1] details = sys.exc_info()[1]
raise exceptions.TestSetupFail(details) raise exceptions.TestSetupFail(details)
try: try:
...@@ -580,20 +582,20 @@ class Test(unittest.TestCase): ...@@ -580,20 +582,20 @@ class Test(unittest.TestCase):
testMethod() testMethod()
except exceptions.TestSetupSkip as details: except exceptions.TestSetupSkip as details:
stacktrace.log_exc_info(sys.exc_info(), logger='avocado.test') stacktrace.log_exc_info(sys.exc_info(), logger=LOG_JOB)
skip_illegal_msg = ('Calling skip() in places other than ' skip_illegal_msg = ('Calling skip() in places other than '
'setUp() is not allowed in avocado, you ' 'setUp() is not allowed in avocado, you '
'must fix your test. Original skip exception: ' 'must fix your test. Original skip exception: '
'%s' % details) '%s' % details)
raise exceptions.TestError(skip_illegal_msg) raise exceptions.TestError(skip_illegal_msg)
except exceptions.TestSkipError as details: except exceptions.TestSkipError as details:
stacktrace.log_exc_info(sys.exc_info(), logger='avocado.test') stacktrace.log_exc_info(sys.exc_info(), logger=LOG_JOB)
raise raise
except exceptions.TestCancel as details: except exceptions.TestCancel as details:
stacktrace.log_exc_info(sys.exc_info(), logger='avocado.test') stacktrace.log_exc_info(sys.exc_info(), logger=LOG_JOB)
raise raise
except: # Old-style exceptions are not inherited from Exception() except: # Old-style exceptions are not inherited from Exception()
stacktrace.log_exc_info(sys.exc_info(), logger='avocado.test') stacktrace.log_exc_info(sys.exc_info(), logger=LOG_JOB)
details = sys.exc_info()[1] details = sys.exc_info()[1]
if not isinstance(details, Exception): # Avoid passing nasty exc if not isinstance(details, Exception): # Avoid passing nasty exc
details = exceptions.TestError("%r: %s" % (details, details)) details = exceptions.TestError("%r: %s" % (details, details))
...@@ -607,14 +609,14 @@ class Test(unittest.TestCase): ...@@ -607,14 +609,14 @@ class Test(unittest.TestCase):
if skip_test is False: if skip_test is False:
self.tearDown() self.tearDown()
except exceptions.TestSetupSkip as details: except exceptions.TestSetupSkip as details:
stacktrace.log_exc_info(sys.exc_info(), logger='avocado.test') stacktrace.log_exc_info(sys.exc_info(), logger=LOG_JOB)
skip_illegal_msg = ('Calling skip() in places other than ' skip_illegal_msg = ('Calling skip() in places other than '
'setUp() is not allowed in avocado, ' 'setUp() is not allowed in avocado, '
'you must fix your test. Original skip ' 'you must fix your test. Original skip '
'exception: %s' % details) 'exception: %s' % details)
raise exceptions.TestError(skip_illegal_msg) raise exceptions.TestError(skip_illegal_msg)
except exceptions.TestSkipError as details: except exceptions.TestSkipError as details:
stacktrace.log_exc_info(sys.exc_info(), logger='avocado.test') stacktrace.log_exc_info(sys.exc_info(), logger=LOG_JOB)
skip_illegal_msg = ('Using skip decorators in tearDown() ' skip_illegal_msg = ('Using skip decorators in tearDown() '
'is not allowed in ' 'is not allowed in '
'avocado, you must fix your ' 'avocado, you must fix your '
...@@ -622,10 +624,10 @@ class Test(unittest.TestCase): ...@@ -622,10 +624,10 @@ class Test(unittest.TestCase):
details) details)
raise exceptions.TestError(skip_illegal_msg) raise exceptions.TestError(skip_illegal_msg)
except exceptions.TestCancel as details: except exceptions.TestCancel as details:
stacktrace.log_exc_info(sys.exc_info(), logger='avocado.test') stacktrace.log_exc_info(sys.exc_info(), logger=LOG_JOB)
raise raise
except: # avoid old-style exception failures except: # avoid old-style exception failures
stacktrace.log_exc_info(sys.exc_info(), logger='avocado.test') stacktrace.log_exc_info(sys.exc_info(), logger=LOG_JOB)
details = sys.exc_info()[1] details = sys.exc_info()[1]
cleanup_exception = exceptions.TestSetupFail(details) cleanup_exception = exceptions.TestSetupFail(details)
...@@ -648,13 +650,13 @@ class Test(unittest.TestCase): ...@@ -648,13 +650,13 @@ class Test(unittest.TestCase):
self._check_reference_stdout() self._check_reference_stdout()
except Exception as details: except Exception as details:
stacktrace.log_exc_info(sys.exc_info(), stacktrace.log_exc_info(sys.exc_info(),
logger='avocado.test') logger=LOG_JOB)
stdout_check_exception = details stdout_check_exception = details
try: try:
self._check_reference_stderr() self._check_reference_stderr()
except Exception as details: except Exception as details:
stacktrace.log_exc_info(sys.exc_info(), stacktrace.log_exc_info(sys.exc_info(),
logger='avocado.test') logger=LOG_JOB)
stderr_check_exception = details stderr_check_exception = details
elif not job_standalone: elif not job_standalone:
if output_check_record in ['all', 'stdout']: if output_check_record in ['all', 'stdout']:
......
...@@ -19,11 +19,11 @@ ...@@ -19,11 +19,11 @@
Multiplex and create variants. Multiplex and create variants.
""" """
import logging
import re import re
from . import tree from . import tree
from . import dispatcher from . import dispatcher
from .output import LOG_JOB
# TODO: Create multiplexer plugin and split these functions into multiple files # TODO: Create multiplexer plugin and split these functions into multiple files
...@@ -45,7 +45,7 @@ class AvocadoParams(object): ...@@ -45,7 +45,7 @@ class AvocadoParams(object):
of duplicate entries inherited from ancestor nodes. It shouldn't produce of duplicate entries inherited from ancestor nodes. It shouldn't produce
false values, though. false values, though.
In this version each new "get()" call is logged into "avocado.test" log. In this version each new "get()" call is logged into avocado.LOG_JOB.
This is subject of change (separate file, perhaps) This is subject of change (separate file, perhaps)
""" """
...@@ -70,7 +70,6 @@ class AvocadoParams(object): ...@@ -70,7 +70,6 @@ class AvocadoParams(object):
path_leaves = self._get_matching_leaves('/*', leaves) path_leaves = self._get_matching_leaves('/*', leaves)
self._abs_path = AvocadoParam(path_leaves, '*: *') self._abs_path = AvocadoParam(path_leaves, '*: *')
self.id = test_id self.id = test_id
self._log = logging.getLogger("avocado.test").debug
self._cache = {} # TODO: Implement something more efficient self._cache = {} # TODO: Implement something more efficient
# TODO: Get rid of this and prepare something better # TODO: Get rid of this and prepare something better
self._default_params = default_params self._default_params = default_params
...@@ -89,13 +88,11 @@ class AvocadoParams(object): ...@@ -89,13 +88,11 @@ class AvocadoParams(object):
def __getstate__(self): def __getstate__(self):
""" log can't be pickled """ """ log can't be pickled """
copy = self.__dict__.copy() copy = self.__dict__.copy()
del(copy['_log'])
return copy return copy
def __setstate__(self, orig): def __setstate__(self, orig):
""" refresh log """ """ refresh log """
self.__dict__.update(orig) self.__dict__.update(orig)
self._log = logging.getLogger("avocado.test").debug
def __repr__(self): def __repr__(self):
return "<AvocadoParams %s>" % self._str() return "<AvocadoParams %s>" % self._str()
...@@ -112,8 +109,8 @@ class AvocadoParams(object): ...@@ -112,8 +109,8 @@ class AvocadoParams(object):
def log(self, key, path, default, value): def log(self, key, path, default, value):
""" Predefined format for displaying params query """ """ Predefined format for displaying params query """
self._log("PARAMS (key=%s, path=%s, default=%s) => %r", key, path, LOG_JOB.debug("PARAMS (key=%s, path=%s, default=%s) => %r", key, path,
default, value) default, value)
def _get_matching_leaves(self, path, leaves): def _get_matching_leaves(self, path, leaves):
""" """
...@@ -169,7 +166,7 @@ class AvocadoParams(object): ...@@ -169,7 +166,7 @@ class AvocadoParams(object):
msg = ("You're probably retrieving param %s via attributes " msg = ("You're probably retrieving param %s via attributes "
" (self.params.$key) which is obsoleted. Use " " (self.params.$key) which is obsoleted. Use "
"self.params.get($key) instead." % attr) "self.params.get($key) instead." % attr)
logging.getLogger("avocado.test").warn(msg) LOG_JOB.warn(msg)
return self.get(attr) return self.get(attr)
def get(self, key, path=None, default=None): def get(self, key, path=None, default=None):
......
...@@ -12,9 +12,8 @@ ...@@ -12,9 +12,8 @@
# Copyright: Red Hat Inc. 2013-2014 # Copyright: Red Hat Inc. 2013-2014
# Author: Lucas Meneghel Rodrigues <lmr@redhat.com> # Author: Lucas Meneghel Rodrigues <lmr@redhat.com>
import logging
from avocado.core import data_dir from avocado.core import data_dir
from avocado.core.output import LOG_UI
from avocado.core.plugin_interfaces import CLICmd from avocado.core.plugin_interfaces import CLICmd
from avocado.core.settings import settings from avocado.core.settings import settings
...@@ -38,15 +37,14 @@ class Config(CLICmd): ...@@ -38,15 +37,14 @@ class Config(CLICmd):
'Current: %(default)s') 'Current: %(default)s')
def run(self, args): def run(self, args):
log = logging.getLogger("avocado.app") LOG_UI.info('Config files read (in order):')
log.info('Config files read (in order):')
for cfg_path in settings.config_paths: for cfg_path in settings.config_paths:
log.debug(' %s' % cfg_path) LOG_UI.debug(' %s' % cfg_path)
if settings.config_paths_failed: if settings.config_paths_failed:
log.error('\nConfig files that failed to read:') LOG_UI.error('\nConfig files that failed to read:')
for cfg_path in settings.config_paths_failed: for cfg_path in settings.config_paths_failed:
log.error(' %s' % cfg_path) LOG_UI.error(' %s' % cfg_path)
log.debug("") LOG_UI.debug("")
if not args.datadir: if not args.datadir:
blength = 0 blength = 0
for section in settings.config.sections(): for section in settings.config.sections():
...@@ -57,18 +55,18 @@ class Config(CLICmd): ...@@ -57,18 +55,18 @@ class Config(CLICmd):
format_str = " %-" + str(blength) + "s %s" format_str = " %-" + str(blength) + "s %s"
log.debug(format_str, 'Section.Key', 'Value') LOG_UI.debug(format_str, 'Section.Key', 'Value')
for section in settings.config.sections(): for section in settings.config.sections():
for value in settings.config.items(section): for value in settings.config.items(section):
config_key = ".".join((section, value[0])) config_key = ".".join((section, value[0]))
log.debug(format_str, config_key, value[1]) LOG_UI.debug(format_str, config_key, value[1])
else: else:
log.debug("Avocado replaces config dirs that can't be accessed") LOG_UI.debug("Avocado replaces config dirs that can't be accessed")
log.debug("with sensible defaults. Please edit your local config") LOG_UI.debug("with sensible defaults. Please edit your local config")
log.debug("file to customize values") LOG_UI.debug("file to customize values")
log.debug('') LOG_UI.debug('')
log.info('Avocado Data Directories:') LOG_UI.info('Avocado Data Directories:')
log.debug(' base ' + data_dir.get_base_dir()) LOG_UI.debug(' base ' + data_dir.get_base_dir())
log.debug(' tests ' + data_dir.get_test_dir()) LOG_UI.debug(' tests ' + data_dir.get_test_dir())
log.debug(' data ' + data_dir.get_data_dir()) LOG_UI.debug(' data ' + data_dir.get_data_dir())
log.debug(' logs ' + data_dir.get_logs_dir()) LOG_UI.debug(' logs ' + data_dir.get_logs_dir())
...@@ -19,7 +19,6 @@ Job Diff ...@@ -19,7 +19,6 @@ Job Diff
from __future__ import absolute_import from __future__ import absolute_import
import argparse import argparse
import json import json
import logging
import os import os
import subprocess import subprocess
import sys import sys
...@@ -31,13 +30,11 @@ from avocado.core import exit_codes ...@@ -31,13 +30,11 @@ from avocado.core import exit_codes
from avocado.core import jobdata from avocado.core import jobdata
from avocado.core import output from avocado.core import output
from avocado.core.output import LOG_UI
from avocado.core.plugin_interfaces import CLICmd from avocado.core.plugin_interfaces import CLICmd
from avocado.core.settings import settings from avocado.core.settings import settings
LOG = logging.getLogger("avocado.app")
class Diff(CLICmd): class Diff(CLICmd):
""" """
...@@ -217,7 +214,7 @@ class Diff(CLICmd): ...@@ -217,7 +214,7 @@ class Diff(CLICmd):
tmp_file2.writelines(job2_results) tmp_file2.writelines(job2_results)
tmp_file2.close() tmp_file2.close()
LOG.info('%s %s', tmp_file1.name, tmp_file2.name) LOG_UI.info('%s %s', tmp_file1.name, tmp_file2.name)
if (getattr(args, 'open_browser', False) and if (getattr(args, 'open_browser', False) and
getattr(args, 'html', None) is None): getattr(args, 'html', None) is None):
...@@ -259,10 +256,10 @@ class Diff(CLICmd): ...@@ -259,10 +256,10 @@ class Diff(CLICmd):
with open(args.html, 'w') as html_file: with open(args.html, 'w') as html_file:
html_file.writelines(job_diff_html.encode("utf-8")) html_file.writelines(job_diff_html.encode("utf-8"))
LOG.info(args.html) LOG_UI.info(args.html)
except IOError as exception: except IOError as exception:
LOG.error(exception) LOG_UI.error(exception)
sys.exit(exit_codes.AVOCADO_FAIL) sys.exit(exit_codes.AVOCADO_FAIL)
if getattr(args, 'open_browser', False): if getattr(args, 'open_browser', False):
...@@ -281,13 +278,13 @@ class Diff(CLICmd): ...@@ -281,13 +278,13 @@ class Diff(CLICmd):
job2_results, job2_results,
fromfile=job1_id, fromfile=job1_id,
tofile=job2_id)): tofile=job2_id)):
LOG.debug(line.strip()) LOG_UI.debug(line.strip())
else: else:
for line in unified_diff(job1_results, for line in unified_diff(job1_results,
job2_results, job2_results,
fromfile=job1_id, fromfile=job1_id,
tofile=job2_id): tofile=job2_id):
LOG.debug(line.strip()) LOG_UI.debug(line.strip())
@staticmethod @staticmethod
def _validate_filters(string): def _validate_filters(string):
...@@ -342,18 +339,18 @@ class Diff(CLICmd): ...@@ -342,18 +339,18 @@ class Diff(CLICmd):
try: try:
resultsdir = jobdata.get_resultsdir(logdir, job_id) resultsdir = jobdata.get_resultsdir(logdir, job_id)
except ValueError as exception: except ValueError as exception:
LOG.error(exception.message) LOG_UI.error(exception.message)
sys.exit(exit_codes.AVOCADO_FAIL) sys.exit(exit_codes.AVOCADO_FAIL)
if resultsdir is None: if resultsdir is None:
LOG.error("Can't find job results directory for '%s' in '%s'", LOG_UI.error("Can't find job results directory for '%s' in '%s'",
job_id, logdir) job_id, logdir)
sys.exit(exit_codes.AVOCADO_FAIL) sys.exit(exit_codes.AVOCADO_FAIL)
sourcejob = jobdata.get_id(os.path.join(resultsdir, 'id'), job_id) sourcejob = jobdata.get_id(os.path.join(resultsdir, 'id'), job_id)
if sourcejob is None: if sourcejob is None:
LOG.error("Can't find matching job id '%s' in '%s' directory.", LOG_UI.error("Can't find matching job id '%s' in '%s' directory.",
job_id, resultsdir) job_id, resultsdir)
sys.exit(exit_codes.AVOCADO_FAIL) sys.exit(exit_codes.AVOCADO_FAIL)
return resultsdir, sourcejob return resultsdir, sourcejob
......
...@@ -14,12 +14,12 @@ ...@@ -14,12 +14,12 @@
import bz2 import bz2
import json import json
import logging
import os import os
import sys import sys
from avocado.core import exit_codes from avocado.core import exit_codes
from avocado.core.plugin_interfaces import CLICmd from avocado.core.plugin_interfaces import CLICmd
from avocado.core.output import LOG_UI
from avocado.utils import distro as utils_distro from avocado.utils import distro as utils_distro
from avocado.utils import path as utils_path from avocado.utils import path as utils_path
from avocado.utils import process from avocado.utils import process
...@@ -340,23 +340,22 @@ class Distro(CLICmd): ...@@ -340,23 +340,22 @@ class Distro(CLICmd):
args.distro_def_arch) args.distro_def_arch)
def run(self, args): def run(self, args):
log = logging.getLogger("avocado.app")
if args.distro_def_create: if args.distro_def_create:
if not (args.distro_def_name and args.distro_def_version and if not (args.distro_def_name and args.distro_def_version and
args.distro_def_arch and args.distro_def_type and args.distro_def_arch and args.distro_def_type and
args.distro_def_path): args.distro_def_path):
log.error('Required arguments: name, version, arch, type ' LOG_UI.error('Required arguments: name, version, arch, type '
'and path') 'and path')
sys.exit(exit_codes.AVOCADO_FAIL) sys.exit(exit_codes.AVOCADO_FAIL)
output_file_name = self.get_output_file_name(args) output_file_name = self.get_output_file_name(args)
if os.path.exists(output_file_name): if os.path.exists(output_file_name):
error_msg = ('Output file "%s" already exists, will not ' error_msg = ('Output file "%s" already exists, will not '
'overwrite it', output_file_name) 'overwrite it', output_file_name)
log.error(error_msg) LOG_UI.error(error_msg)
else: else:
log.debug("Loading distro information from tree... " LOG_UI.debug("Loading distro information from tree... "
"Please wait...") "Please wait...")
distro = load_from_tree(args.distro_def_name, distro = load_from_tree(args.distro_def_name,
args.distro_def_version, args.distro_def_version,
args.distro_def_release, args.distro_def_release,
...@@ -364,10 +363,10 @@ class Distro(CLICmd): ...@@ -364,10 +363,10 @@ class Distro(CLICmd):
args.distro_def_type, args.distro_def_type,
args.distro_def_path) args.distro_def_path)
save_distro(distro, output_file_name) save_distro(distro, output_file_name)
log.debug('Distro information saved to "%s"', LOG_UI.debug('Distro information saved to "%s"',
output_file_name) output_file_name)
else: else:
detected = utils_distro.detect() detected = utils_distro.detect()
log.debug('Detected distribution: %s (%s) version %s release %s', LOG_UI.debug('Detected distribution: %s (%s) version %s release '
detected.name, detected.arch, detected.version, '%s', detected.name, detected.arch, detected.version,
detected.release) detected.release)
...@@ -14,11 +14,11 @@ ...@@ -14,11 +14,11 @@
Libexec PATHs modifier Libexec PATHs modifier
""" """
import logging
import os import os
import sys import sys
from avocado.core import exit_codes from avocado.core import exit_codes
from avocado.core.output import LOG_UI
from avocado.core.plugin_interfaces import CLICmd from avocado.core.plugin_interfaces import CLICmd
...@@ -37,21 +37,20 @@ class ExecPath(CLICmd): ...@@ -37,21 +37,20 @@ class ExecPath(CLICmd):
:param args: Command line args received from the run subparser. :param args: Command line args received from the run subparser.
""" """
log = logging.getLogger("avocado.app")
if 'VIRTUAL_ENV' in os.environ: if 'VIRTUAL_ENV' in os.environ:
log.debug('libexec') LOG_UI.debug('libexec')
elif os.path.exists('/usr/libexec/avocado'): elif os.path.exists('/usr/libexec/avocado'):
log.debug('/usr/libexec/avocado') LOG_UI.debug('/usr/libexec/avocado')
elif os.path.exists('/usr/lib/avocado'): elif os.path.exists('/usr/lib/avocado'):
log.debug('/usr/lib/avocado') LOG_UI.debug('/usr/lib/avocado')
else: else:
for path in os.environ.get('PATH').split(':'): for path in os.environ.get('PATH').split(':'):
if (os.path.exists(os.path.join(path, 'avocado')) and if (os.path.exists(os.path.join(path, 'avocado')) and
os.path.exists(os.path.join(os.path.dirname(path), os.path.exists(os.path.join(os.path.dirname(path),
'libexec'))): 'libexec'))):
log.debug(os.path.join(os.path.dirname(path), 'libexec')) LOG_UI.debug(os.path.join(os.path.dirname(path), 'libexec'))
break break
else: else:
log.error("Can't locate avocado libexec path") LOG_UI.error("Can't locate avocado libexec path")
sys.exit(exit_codes.AVOCADO_FAIL) sys.exit(exit_codes.AVOCADO_FAIL)
return sys.exit(exit_codes.AVOCADO_ALL_OK) return sys.exit(exit_codes.AVOCADO_ALL_OK)
...@@ -15,8 +15,7 @@ ...@@ -15,8 +15,7 @@
Human result UI Human result UI
""" """
import logging from avocado.core.output import LOG_UI
from avocado.core.plugin_interfaces import ResultEvents from avocado.core.plugin_interfaces import ResultEvents
from avocado.core.plugin_interfaces import JobPre, JobPost from avocado.core.plugin_interfaces import JobPre, JobPost
from avocado.core import output from avocado.core import output
...@@ -40,7 +39,6 @@ class Human(ResultEvents): ...@@ -40,7 +39,6 @@ class Human(ResultEvents):
'CANCEL': output.TERM_SUPPORT.CANCEL} 'CANCEL': output.TERM_SUPPORT.CANCEL}
def __init__(self, args): def __init__(self, args):
self.log = logging.getLogger("avocado.app")
self.__throbber = output.Throbber() self.__throbber = output.Throbber()
stdout_claimed_by = getattr(args, 'stdout_claimed_by', None) stdout_claimed_by = getattr(args, 'stdout_claimed_by', None)
self.owns_stdout = not stdout_claimed_by self.owns_stdout = not stdout_claimed_by
...@@ -48,11 +46,11 @@ class Human(ResultEvents): ...@@ -48,11 +46,11 @@ class Human(ResultEvents):
def pre_tests(self, job): def pre_tests(self, job):
if not self.owns_stdout: if not self.owns_stdout:
return return
self.log.info("JOB ID : %s", job.unique_id) LOG_UI.info("JOB ID : %s", job.unique_id)
replay_source_job = getattr(job.args, "replay_sourcejob", False) replay_source_job = getattr(job.args, "replay_sourcejob", False)
if replay_source_job: if replay_source_job:
self.log.info("SRC JOB ID : %s", replay_source_job) LOG_UI.info("SRC JOB ID : %s", replay_source_job)
self.log.info("JOB LOG : %s", job.logfile) LOG_UI.info("JOB LOG : %s", job.logfile)
def start_test(self, result, state): def start_test(self, result, state):
if not self.owns_stdout: if not self.owns_stdout:
...@@ -64,8 +62,8 @@ class Human(ResultEvents): ...@@ -64,8 +62,8 @@ class Human(ResultEvents):
else: else:
name = "<unknown>" name = "<unknown>"
uid = '?' uid = '?'
self.log.debug(' (%s/%s) %s: ', uid, result.tests_total, name, LOG_UI.debug(' (%s/%s) %s: ', uid, result.tests_total, name,
extra={"skip_newline": True}) extra={"skip_newline": True})
def test_progress(self, progress=False): def test_progress(self, progress=False):
if not self.owns_stdout: if not self.owns_stdout:
...@@ -74,8 +72,8 @@ class Human(ResultEvents): ...@@ -74,8 +72,8 @@ class Human(ResultEvents):
color = output.TERM_SUPPORT.PASS color = output.TERM_SUPPORT.PASS
else: else:
color = output.TERM_SUPPORT.PARTIAL color = output.TERM_SUPPORT.PARTIAL
self.log.debug(color + self.__throbber.render() + LOG_UI.debug(color + self.__throbber.render() +
output.TERM_SUPPORT.ENDC, extra={"skip_newline": True}) output.TERM_SUPPORT.ENDC, extra={"skip_newline": True})
def end_test(self, result, state): def end_test(self, result, state):
if not self.owns_stdout: if not self.owns_stdout:
...@@ -86,19 +84,19 @@ class Human(ResultEvents): ...@@ -86,19 +84,19 @@ class Human(ResultEvents):
duration = (" (%.2f s)" % state.get('time_elapsed', -1) duration = (" (%.2f s)" % state.get('time_elapsed', -1)
if status != "SKIP" if status != "SKIP"
else "") else "")
self.log.debug(output.TERM_SUPPORT.MOVE_BACK + LOG_UI.debug(output.TERM_SUPPORT.MOVE_BACK +
self.output_mapping[status] + self.output_mapping[status] +
status + output.TERM_SUPPORT.ENDC + status + output.TERM_SUPPORT.ENDC +
duration) duration)
def post_tests(self, job): def post_tests(self, job):
if not self.owns_stdout: if not self.owns_stdout:
return return
self.log.info("RESULTS : PASS %d | ERROR %d | FAIL %d | SKIP %d | " LOG_UI.info("RESULTS : PASS %d | ERROR %d | FAIL %d | SKIP %d | "
"WARN %d | INTERRUPT %s | CANCEL %s", job.result.passed, "WARN %d | INTERRUPT %s | CANCEL %s", job.result.passed,
job.result.errors, job.result.failed, job.result.skipped, job.result.errors, job.result.failed, job.result.skipped,
job.result.warned, job.result.interrupted, job.result.warned, job.result.interrupted,
job.result.cancelled) job.result.cancelled)
class HumanJob(JobPre, JobPost): class HumanJob(JobPre, JobPost):
...@@ -116,5 +114,4 @@ class HumanJob(JobPre, JobPost): ...@@ -116,5 +114,4 @@ class HumanJob(JobPre, JobPost):
def post(self, job): def post(self, job):
if job.time_elapsed != -1: if job.time_elapsed != -1:
if not getattr(job.args, 'stdout_claimed_by', None): if not getattr(job.args, 'stdout_claimed_by', None):
log = logging.getLogger("avocado.app") LOG_UI.info("JOB TIME : %.2f s", job.time_elapsed)
log.info("JOB TIME : %.2f s", job.time_elapsed)
import os import os
import logging
from avocado.core.output import LOG_UI
from avocado.core.plugin_interfaces import JobPre, JobPost from avocado.core.plugin_interfaces import JobPre, JobPost
from avocado.core.settings import settings from avocado.core.settings import settings
from avocado.utils import process from avocado.utils import process
...@@ -15,7 +15,6 @@ class JobScripts(JobPre, JobPost): ...@@ -15,7 +15,6 @@ class JobScripts(JobPre, JobPost):
description = 'Runs scripts before/after the job is run' description = 'Runs scripts before/after the job is run'
def __init__(self): def __init__(self):
self.log = logging.getLogger("avocado.app")
self.warn_non_existing_dir = settings.get_value(section=CONFIG_SECTION, self.warn_non_existing_dir = settings.get_value(section=CONFIG_SECTION,
key="warn_non_existing_dir", key="warn_non_existing_dir",
key_type=bool, key_type=bool,
...@@ -28,8 +27,8 @@ class JobScripts(JobPre, JobPost): ...@@ -28,8 +27,8 @@ class JobScripts(JobPre, JobPost):
def _run_scripts(self, kind, scripts_dir, job): def _run_scripts(self, kind, scripts_dir, job):
if not os.path.isdir(scripts_dir): if not os.path.isdir(scripts_dir):
if self.warn_non_existing_dir: if self.warn_non_existing_dir:
self.log.error("Directory configured to hold %s-job scripts " LOG_UI.error("Directory configured to hold %s-job scripts "
"has not been found: %s", kind, scripts_dir) "has not been found: %s", kind, scripts_dir)
return return
dir_list = os.listdir(scripts_dir) dir_list = os.listdir(scripts_dir)
...@@ -44,8 +43,8 @@ class JobScripts(JobPre, JobPost): ...@@ -44,8 +43,8 @@ class JobScripts(JobPre, JobPost):
for script in scripts: for script in scripts:
result = process.run(script, ignore_status=True, env=env) result = process.run(script, ignore_status=True, env=env)
if (result.exit_status != 0) and self.warn_non_zero_status: if (result.exit_status != 0) and self.warn_non_zero_status:
self.log.error('%s job script "%s" exited with status "%i"', LOG_UI.error('%s job script "%s" exited with status "%i"',
kind.capitalize(), script, result.exit_status) kind.capitalize(), script, result.exit_status)
@staticmethod @staticmethod
def _job_to_environment_variables(job): def _job_to_environment_variables(job):
......
...@@ -18,9 +18,9 @@ JSON output module. ...@@ -18,9 +18,9 @@ JSON output module.
""" """
import json import json
import logging
import os import os
from avocado.core.output import LOG_UI
from avocado.core.parser import FileOrStdoutAction from avocado.core.parser import FileOrStdoutAction
from avocado.core.plugin_interfaces import CLI, Result from avocado.core.plugin_interfaces import CLI, Result
...@@ -86,8 +86,7 @@ class JSONResult(Result): ...@@ -86,8 +86,7 @@ class JSONResult(Result):
json_path = getattr(job.args, 'json_output', 'None') json_path = getattr(job.args, 'json_output', 'None')
if json_path is not None: if json_path is not None:
if json_path == '-': if json_path == '-':
log = logging.getLogger("avocado.app") LOG_UI.debug(content)
log.debug(content)
else: else:
with open(json_path, 'w') as json_file: with open(json_path, 'w') as json_file:
json_file.write(content) json_file.write(content)
......
...@@ -12,13 +12,13 @@ ...@@ -12,13 +12,13 @@
# Copyright: Red Hat Inc. 2013-2014 # Copyright: Red Hat Inc. 2013-2014
# Author: Lucas Meneghel Rodrigues <lmr@redhat.com> # Author: Lucas Meneghel Rodrigues <lmr@redhat.com>
import logging
import sys import sys
from avocado.core import exit_codes, output from avocado.core import exit_codes, output
from avocado.core import loader from avocado.core import loader
from avocado.core import test from avocado.core import test
from avocado.core.output import LOG_UI
from avocado.core.plugin_interfaces import CLICmd from avocado.core.plugin_interfaces import CLICmd
from avocado.utils import astring from avocado.utils import astring
...@@ -30,7 +30,6 @@ class TestLister(object): ...@@ -30,7 +30,6 @@ class TestLister(object):
""" """
def __init__(self, args): def __init__(self, args):
self.log = logging.getLogger("avocado.app")
try: try:
loader.loader.load_plugins(args) loader.loader.load_plugins(args)
except loader.LoaderError as details: except loader.LoaderError as details:
...@@ -48,7 +47,7 @@ class TestLister(object): ...@@ -48,7 +47,7 @@ class TestLister(object):
return loader.loader.discover(paths, return loader.loader.discover(paths,
which_tests=which_tests) which_tests=which_tests)
except loader.LoaderUnhandledReferenceError as details: except loader.LoaderUnhandledReferenceError as details:
self.log.error(str(details)) LOG_UI.error(str(details))
sys.exit(exit_codes.AVOCADO_FAIL) sys.exit(exit_codes.AVOCADO_FAIL)
def _get_test_matrix(self, test_suite): def _get_test_matrix(self, test_suite):
...@@ -90,12 +89,12 @@ class TestLister(object): ...@@ -90,12 +89,12 @@ class TestLister(object):
output.TERM_SUPPORT.header_str('Test')) output.TERM_SUPPORT.header_str('Test'))
for line in astring.iter_tabular_output(test_matrix, header=header): for line in astring.iter_tabular_output(test_matrix, header=header):
self.log.debug(line) LOG_UI.debug(line)
if self.args.verbose: if self.args.verbose:
self.log.debug("") LOG_UI.debug("")
for key in sorted(stats): for key in sorted(stats):
self.log.info("%s: %s", key.upper(), stats[key]) LOG_UI.info("%s: %s", key.upper(), stats[key])
def _list(self): def _list(self):
self._extra_listing() self._extra_listing()
...@@ -112,7 +111,7 @@ class TestLister(object): ...@@ -112,7 +111,7 @@ class TestLister(object):
try: try:
self._list() self._list()
except KeyboardInterrupt: except KeyboardInterrupt:
self.log.error('Command interrupted by user...') LOG_UI.error('Command interrupted by user...')
return exit_codes.AVOCADO_FAIL return exit_codes.AVOCADO_FAIL
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
# Copyright: Red Hat Inc. 2013-2014 # Copyright: Red Hat Inc. 2013-2014
# Author: Lucas Meneghel Rodrigues <lmr@redhat.com> # Author: Lucas Meneghel Rodrigues <lmr@redhat.com>
import logging from avocado.core.output import LOG_UI
from .variants import Variants from .variants import Variants
...@@ -27,8 +27,7 @@ class Multiplex(Variants): ...@@ -27,8 +27,7 @@ class Multiplex(Variants):
name = "multiplex" name = "multiplex"
def run(self, args): def run(self, args):
log = logging.getLogger("avocado.app") LOG_UI.warning("The 'avocado multiplex' command is deprecated by the "
log.warning("The 'avocado multiplex' command is deprecated by the " "'avocado variants' one. Please start using that one "
"'avocado variants' one. Please start using that one " "instead as this will be removed in Avocado 52.0.")
"instead as this will be removed in Avocado 52.0.")
super(Multiplex, self).run(args) super(Multiplex, self).run(args)
...@@ -15,9 +15,8 @@ ...@@ -15,9 +15,8 @@
Plugins information plugin Plugins information plugin
""" """
import logging
from avocado.core import dispatcher from avocado.core import dispatcher
from avocado.core.output import LOG_UI
from avocado.core.plugin_interfaces import CLICmd from avocado.core.plugin_interfaces import CLICmd
from avocado.utils import astring from avocado.utils import astring
...@@ -39,7 +38,6 @@ class Plugins(CLICmd): ...@@ -39,7 +38,6 @@ class Plugins(CLICmd):
'Current: %(default)s') 'Current: %(default)s')
def run(self, args): def run(self, args):
log = logging.getLogger("avocado.app")
plugin_types = [ plugin_types = [
(dispatcher.CLICmdDispatcher(), (dispatcher.CLICmdDispatcher(),
'Plugins that add new commands (cli.cmd):'), 'Plugins that add new commands (cli.cmd):'),
...@@ -56,13 +54,13 @@ class Plugins(CLICmd): ...@@ -56,13 +54,13 @@ class Plugins(CLICmd):
'Plugins that generate test variants (varianter): ') 'Plugins that generate test variants (varianter): ')
] ]
for plugins_active, msg in plugin_types: for plugins_active, msg in plugin_types:
log.info(msg) LOG_UI.info(msg)
plugin_matrix = [] plugin_matrix = []
for plugin in sorted(plugins_active, key=lambda x: x.name): for plugin in sorted(plugins_active, key=lambda x: x.name):
plugin_matrix.append((plugin.name, plugin.obj.description)) plugin_matrix.append((plugin.name, plugin.obj.description))
if not plugin_matrix: if not plugin_matrix:
log.debug("(No active plugin)") LOG_UI.debug("(No active plugin)")
else: else:
for line in astring.iter_tabular_output(plugin_matrix): for line in astring.iter_tabular_output(plugin_matrix):
log.debug(line) LOG_UI.debug(line)
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
import argparse import argparse
import json import json
import logging
import os import os
import re import re
import sys import sys
...@@ -23,6 +22,7 @@ from avocado.core import exit_codes ...@@ -23,6 +22,7 @@ from avocado.core import exit_codes
from avocado.core import jobdata from avocado.core import jobdata
from avocado.core import status from avocado.core import status
from avocado.core.output import LOG_UI
from avocado.core.plugin_interfaces import CLI from avocado.core.plugin_interfaces import CLI
from avocado.core.settings import settings from avocado.core.settings import settings
from avocado.core.test import ReplaySkipTest from avocado.core.test import ReplaySkipTest
...@@ -165,8 +165,6 @@ class Replay(CLI): ...@@ -165,8 +165,6 @@ class Replay(CLI):
if getattr(args, 'replay_jobid', None) is None: if getattr(args, 'replay_jobid', None) is None:
return return
log = logging.getLogger("avocado.app")
err = None err = None
if args.replay_teststatus and 'variants' in args.replay_ignore: if args.replay_teststatus and 'variants' in args.replay_ignore:
err = ("Option `--replay-test-status` is incompatible with " err = ("Option `--replay-test-status` is incompatible with "
...@@ -177,7 +175,7 @@ class Replay(CLI): ...@@ -177,7 +175,7 @@ class Replay(CLI):
elif args.remote_hostname: elif args.remote_hostname:
err = "Currently we don't replay jobs in remote hosts." err = "Currently we don't replay jobs in remote hosts."
if err is not None: if err is not None:
log.error(err) LOG_UI.error(err)
sys.exit(exit_codes.AVOCADO_FAIL) sys.exit(exit_codes.AVOCADO_FAIL)
if getattr(args, 'logdir', None) is not None: if getattr(args, 'logdir', None) is not None:
...@@ -189,11 +187,11 @@ class Replay(CLI): ...@@ -189,11 +187,11 @@ class Replay(CLI):
try: try:
resultsdir = jobdata.get_resultsdir(logdir, args.replay_jobid) resultsdir = jobdata.get_resultsdir(logdir, args.replay_jobid)
except ValueError as exception: except ValueError as exception:
log.error(exception.message) LOG_UI.error(exception.message)
sys.exit(exit_codes.AVOCADO_FAIL) sys.exit(exit_codes.AVOCADO_FAIL)
if resultsdir is None: if resultsdir is None:
log.error("Can't find job results directory in '%s'", logdir) LOG_UI.error("Can't find job results directory in '%s'", logdir)
sys.exit(exit_codes.AVOCADO_FAIL) sys.exit(exit_codes.AVOCADO_FAIL)
sourcejob = jobdata.get_id(os.path.join(resultsdir, 'id'), sourcejob = jobdata.get_id(os.path.join(resultsdir, 'id'),
...@@ -201,7 +199,7 @@ class Replay(CLI): ...@@ -201,7 +199,7 @@ class Replay(CLI):
if sourcejob is None: if sourcejob is None:
msg = ("Can't find matching job id '%s' in '%s' directory." msg = ("Can't find matching job id '%s' in '%s' directory."
% (args.replay_jobid, resultsdir)) % (args.replay_jobid, resultsdir))
log.error(msg) LOG_UI.error(msg)
sys.exit(exit_codes.AVOCADO_FAIL) sys.exit(exit_codes.AVOCADO_FAIL)
setattr(args, 'replay_sourcejob', sourcejob) setattr(args, 'replay_sourcejob', sourcejob)
...@@ -212,45 +210,47 @@ class Replay(CLI): ...@@ -212,45 +210,47 @@ class Replay(CLI):
'external_runner_chdir', 'external_runner_chdir',
'failfast'] 'failfast']
if replay_args is None: if replay_args is None:
log.warn('Source job args data not found. These options will not ' LOG_UI.warn('Source job args data not found. These options will '
'be loaded in this replay job: %s', ', '.join(whitelist)) 'not be loaded in this replay job: %s',
', '.join(whitelist))
else: else:
for option in whitelist: for option in whitelist:
optvalue = getattr(args, option, None) optvalue = getattr(args, option, None)
if optvalue is not None: if optvalue is not None:
log.warn("Overriding the replay %s with the --%s value " LOG_UI.warn("Overriding the replay %s with the --%s value "
"given on the command line.", "given on the command line.",
option.replace('_', '-'), option.replace('_', '-'),
option.replace('_', '-')) option.replace('_', '-'))
else: else:
setattr(args, option, replay_args[option]) setattr(args, option, replay_args[option])
# Keeping this for compatibility. # Keeping this for compatibility.
# TODO: Use replay_args['reference'] at some point in the future. # TODO: Use replay_args['reference'] at some point in the future.
if getattr(args, 'reference', None): if getattr(args, 'reference', None):
log.warn('Overriding the replay test references with test ' LOG_UI.warn('Overriding the replay test references with test '
'references given in the command line.') 'references given in the command line.')
else: else:
references = jobdata.retrieve_references(resultsdir) references = jobdata.retrieve_references(resultsdir)
if references is None: if references is None:
log.error('Source job test references data not found. Aborting.') LOG_UI.error('Source job test references data not found. '
'Aborting.')
sys.exit(exit_codes.AVOCADO_FAIL) sys.exit(exit_codes.AVOCADO_FAIL)
else: else:
setattr(args, 'reference', references) setattr(args, 'reference', references)
if 'config' in args.replay_ignore: if 'config' in args.replay_ignore:
log.warn("Ignoring configuration from source job with " LOG_UI.warn("Ignoring configuration from source job with "
"--replay-ignore.") "--replay-ignore.")
else: else:
self.load_config(resultsdir) self.load_config(resultsdir)
if 'variants' in args.replay_ignore: if 'variants' in args.replay_ignore:
log.warn("Ignoring variants from source job with " LOG_UI.warn("Ignoring variants from source job with "
"--replay-ignore.") "--replay-ignore.")
else: else:
variants = jobdata.retrieve_variants(resultsdir) variants = jobdata.retrieve_variants(resultsdir)
if variants is None: if variants is None:
log.error('Source job variants data not found. Aborting.') LOG_UI.error('Source job variants data not found. Aborting.')
sys.exit(exit_codes.AVOCADO_FAIL) sys.exit(exit_codes.AVOCADO_FAIL)
else: else:
# Ignore data manipulation. This is necessary, because # Ignore data manipulation. This is necessary, because
...@@ -258,8 +258,9 @@ class Replay(CLI): ...@@ -258,8 +258,9 @@ class Replay(CLI):
# are other plugins running before/after this which might # are other plugins running before/after this which might
# want to alter the variants object. # want to alter the variants object.
if args.avocado_variants.is_parsed(): if args.avocado_variants.is_parsed():
log.warning("Using src job Mux data only, use `--replay-" LOG_UI.warning("Using src job Mux data only, use "
"ignore variants` to override them.") "`--replay-ignore variants` to override "
"them.")
setattr(args, "avocado_variants", variants) setattr(args, "avocado_variants", variants)
# Extend "replay_test_status" of "INTERRUPTED" when --replay-resume # Extend "replay_test_status" of "INTERRUPTED" when --replay-resume
...@@ -280,5 +281,5 @@ class Replay(CLI): ...@@ -280,5 +281,5 @@ class Replay(CLI):
if os.path.exists(pwd): if os.path.exists(pwd):
os.chdir(pwd) os.chdir(pwd)
else: else:
log.warn("Directory used in the replay source job '%s' does " LOG_UI.warn("Directory used in the replay source job '%s' does"
"not exist, using '.' instead", pwd) " not exist, using '.' instead", pwd)
...@@ -17,13 +17,13 @@ Base Test Runner Plugins. ...@@ -17,13 +17,13 @@ Base Test Runner Plugins.
""" """
import argparse import argparse
import logging
import sys import sys
from avocado.core import exit_codes from avocado.core import exit_codes
from avocado.core import job from avocado.core import job
from avocado.core import loader from avocado.core import loader
from avocado.core import output from avocado.core import output
from avocado.core.output import LOG_UI
from avocado.core.plugin_interfaces import CLICmd from avocado.core.plugin_interfaces import CLICmd
from avocado.core.dispatcher import ResultDispatcher from avocado.core.dispatcher import ResultDispatcher
from avocado.core.dispatcher import JobPrePostDispatcher from avocado.core.dispatcher import JobPrePostDispatcher
...@@ -153,21 +153,19 @@ class Run(CLICmd): ...@@ -153,21 +153,19 @@ class Run(CLICmd):
:param args: Command line args received from the run subparser. :param args: Command line args received from the run subparser.
""" """
log = logging.getLogger("avocado.app")
if args.unique_job_id is not None: if args.unique_job_id is not None:
try: try:
int(args.unique_job_id, 16) int(args.unique_job_id, 16)
if len(args.unique_job_id) != 40: if len(args.unique_job_id) != 40:
raise ValueError raise ValueError
except ValueError: except ValueError:
log.error('Unique Job ID needs to be a 40 digit hex number') LOG_UI.error('Unique Job ID needs to be a 40 digit hex number')
sys.exit(exit_codes.AVOCADO_FAIL) sys.exit(exit_codes.AVOCADO_FAIL)
try: try:
args.job_timeout = time_to_seconds(args.job_timeout) args.job_timeout = time_to_seconds(args.job_timeout)
except ValueError as e: except ValueError as e:
log.error(e.message) LOG_UI.error(e.message)
sys.exit(exit_codes.AVOCADO_FAIL) sys.exit(exit_codes.AVOCADO_FAIL)
job_instance = job.Job(args) job_instance = job.Job(args)
pre_post_dispatcher = JobPrePostDispatcher() pre_post_dispatcher = JobPrePostDispatcher()
try: try:
......
...@@ -15,9 +15,9 @@ ...@@ -15,9 +15,9 @@
TAP output module. TAP output module.
""" """
import logging
import os import os
from avocado.core.output import LOG_UI
from avocado.core.parser import FileOrStdoutAction from avocado.core.parser import FileOrStdoutAction
from avocado.core.plugin_interfaces import CLI, ResultEvents from avocado.core.plugin_interfaces import CLI, ResultEvents
...@@ -63,7 +63,7 @@ class TAPResult(ResultEvents): ...@@ -63,7 +63,7 @@ class TAPResult(ResultEvents):
self.__open_files = [] self.__open_files = []
output = getattr(args, 'tap', None) output = getattr(args, 'tap', None)
if output == '-': if output == '-':
log = logging.getLogger("avocado.app").debug log = LOG_UI.debug
self.__logs.append(log) self.__logs.append(log)
elif output is not None: elif output is not None:
log = open(output, "w", 1) log = open(output, "w", 1)
......
...@@ -13,10 +13,10 @@ ...@@ -13,10 +13,10 @@
# Author: Lucas Meneghel Rodrigues <lmr@redhat.com> # Author: Lucas Meneghel Rodrigues <lmr@redhat.com>
# Author: Lukas Doktor <ldoktor@redhat.com> # Author: Lukas Doktor <ldoktor@redhat.com>
import logging
import sys import sys
from avocado.core import exit_codes from avocado.core import exit_codes
from avocado.core.output import LOG_UI
from avocado.core.plugin_interfaces import CLICmd from avocado.core.plugin_interfaces import CLICmd
from avocado.core.settings import settings from avocado.core.settings import settings
...@@ -79,20 +79,19 @@ class Variants(CLICmd): ...@@ -79,20 +79,19 @@ class Variants(CLICmd):
"inherited values") "inherited values")
def run(self, args): def run(self, args):
log = logging.getLogger("avocado.app")
err = None err = None
if args.tree and args.mux_debug: if args.tree and args.mux_debug:
err = "Option --tree is incompatible with --debug." err = "Option --tree is incompatible with --debug."
elif not args.tree and args.inherit: elif not args.tree and args.inherit:
err = "Option --inherit can be only used with --tree" err = "Option --inherit can be only used with --tree"
if err: if err:
log.error(err) LOG_UI.error(err)
sys.exit(exit_codes.AVOCADO_FAIL) sys.exit(exit_codes.AVOCADO_FAIL)
varianter = args.avocado_variants varianter = args.avocado_variants
try: try:
varianter.parse(args) varianter.parse(args)
except (IOError, ValueError) as details: except (IOError, ValueError) as details:
log.error("Unable to parse varianter: %s", details) LOG_UI.error("Unable to parse varianter: %s", details)
sys.exit(exit_codes.AVOCADO_FAIL) sys.exit(exit_codes.AVOCADO_FAIL)
use_utf8 = settings.get_value("runner.output", "utf8", use_utf8 = settings.get_value("runner.output", "utf8",
key_type=bool, default=None) key_type=bool, default=None)
...@@ -116,6 +115,6 @@ class Variants(CLICmd): ...@@ -116,6 +115,6 @@ class Variants(CLICmd):
variants=variants, variants=variants,
use_utf8=use_utf8) use_utf8=use_utf8)
for line in lines.splitlines(): for line in lines.splitlines():
log.debug(line) LOG_UI.debug(line)
sys.exit(exit_codes.AVOCADO_ALL_OK) sys.exit(exit_codes.AVOCADO_ALL_OK)
...@@ -12,11 +12,11 @@ ...@@ -12,11 +12,11 @@
# Copyright: Red Hat Inc. 2014 # Copyright: Red Hat Inc. 2014
# Author: Ruda Moura <rmoura@redhat.com> # Author: Ruda Moura <rmoura@redhat.com>
import logging
import os import os
import sys import sys
from avocado.core import exit_codes from avocado.core import exit_codes
from avocado.core.output import LOG_UI
from avocado.core.plugin_interfaces import CLI from avocado.core.plugin_interfaces import CLI
from avocado.utils import process from avocado.utils import process
...@@ -50,10 +50,9 @@ class Wrapper(CLI): ...@@ -50,10 +50,9 @@ class Wrapper(CLI):
def run(self, args): def run(self, args):
wraps = getattr(args, "wrapper", None) wraps = getattr(args, "wrapper", None)
if wraps: if wraps:
log = logging.getLogger("avocado.app")
if getattr(args, 'gdb_run_bin', None): if getattr(args, 'gdb_run_bin', None):
log.error('Command line option --wrapper is incompatible' LOG_UI.error('Command line option --wrapper is incompatible'
' with option --gdb-run-bin.\n%s', args.wrapper) ' with option --gdb-run-bin.\n%s', args.wrapper)
sys.exit(exit_codes.AVOCADO_FAIL) sys.exit(exit_codes.AVOCADO_FAIL)
for wrap in args.wrapper: for wrap in args.wrapper:
...@@ -62,13 +61,13 @@ class Wrapper(CLI): ...@@ -62,13 +61,13 @@ class Wrapper(CLI):
script = os.path.abspath(wrap) script = os.path.abspath(wrap)
process.WRAP_PROCESS = os.path.abspath(script) process.WRAP_PROCESS = os.path.abspath(script)
else: else:
log.error("You can't have multiple global " LOG_UI.error("You can't have multiple global "
"wrappers at once.") "wrappers at once.")
sys.exit(exit_codes.AVOCADO_FAIL) sys.exit(exit_codes.AVOCADO_FAIL)
else: else:
script, cmd = wrap.split(':', 1) script, cmd = wrap.split(':', 1)
script = os.path.abspath(script) script = os.path.abspath(script)
process.WRAP_PROCESS_NAMES_EXPR.append((script, cmd)) process.WRAP_PROCESS_NAMES_EXPR.append((script, cmd))
if not os.path.exists(script): if not os.path.exists(script):
log.error("Wrapper '%s' not found!", script) LOG_UI.error("Wrapper '%s' not found!", script)
sys.exit(exit_codes.AVOCADO_FAIL) sys.exit(exit_codes.AVOCADO_FAIL)
...@@ -16,12 +16,12 @@ ...@@ -16,12 +16,12 @@
"""xUnit module.""" """xUnit module."""
import datetime import datetime
import logging
import os import os
import string import string
from xml.dom.minidom import Document, Element from xml.dom.minidom import Document, Element
from avocado.core.parser import FileOrStdoutAction from avocado.core.parser import FileOrStdoutAction
from avocado.core.output import LOG_UI
from avocado.core.plugin_interfaces import CLI, Result from avocado.core.plugin_interfaces import CLI, Result
...@@ -123,8 +123,7 @@ class XUnitResult(Result): ...@@ -123,8 +123,7 @@ class XUnitResult(Result):
xunit_path = getattr(job.args, 'xunit_output', 'None') xunit_path = getattr(job.args, 'xunit_output', 'None')
if xunit_path is not None: if xunit_path is not None:
if xunit_path == '-': if xunit_path == '-':
log = logging.getLogger("avocado.app") LOG_UI.debug(content)
log.debug(content)
else: else:
with open(xunit_path, 'w') as xunit_file: with open(xunit_path, 'w') as xunit_file:
xunit_file.write(content) xunit_file.write(content)
......
...@@ -14,12 +14,12 @@ ...@@ -14,12 +14,12 @@
"""Multiplexer plugin to parse yaml files to params""" """Multiplexer plugin to parse yaml files to params"""
import copy import copy
import logging
import os import os
import re import re
import sys import sys
from avocado.core import tree, exit_codes, mux from avocado.core import tree, exit_codes, mux
from avocado.core.output import LOG_UI
from avocado.core.plugin_interfaces import CLI, Varianter from avocado.core.plugin_interfaces import CLI, Varianter
...@@ -332,10 +332,10 @@ class YamlToMux(mux.MuxPlugin, Varianter): ...@@ -332,10 +332,10 @@ class YamlToMux(mux.MuxPlugin, Varianter):
@staticmethod @staticmethod
def _log_deprecation_msg(deprecated, current): def _log_deprecation_msg(deprecated, current):
""" """
Log a message into the "avocado.app" warning log Log a message into the avocado.LOG_UI warning log
""" """
msg = "The use of '%s' is deprecated, please use '%s' instead" msg = "The use of '%s' is deprecated, please use '%s' instead"
logging.getLogger("avocado.app").warning(msg, deprecated, current) LOG_UI.warning(msg, deprecated, current)
def initialize(self, args): def initialize(self, args):
# Deprecated filters # Deprecated filters
...@@ -369,7 +369,7 @@ class YamlToMux(mux.MuxPlugin, Varianter): ...@@ -369,7 +369,7 @@ class YamlToMux(mux.MuxPlugin, Varianter):
data.merge(create_from_yaml(multiplex_files, debug)) data.merge(create_from_yaml(multiplex_files, debug))
except IOError as details: except IOError as details:
error_msg = "%s : %s" % (details.strerror, details.filename) error_msg = "%s : %s" % (details.strerror, details.filename)
logging.getLogger("avocado.app").error(error_msg) LOG_UI.error(error_msg)
if args.subcommand == 'run': if args.subcommand == 'run':
sys.exit(exit_codes.AVOCADO_JOB_FAIL) sys.exit(exit_codes.AVOCADO_JOB_FAIL)
else: else:
...@@ -385,7 +385,7 @@ class YamlToMux(mux.MuxPlugin, Varianter): ...@@ -385,7 +385,7 @@ class YamlToMux(mux.MuxPlugin, Varianter):
args.avocado_variants.data_merge(from_yaml) args.avocado_variants.data_merge(from_yaml)
except IOError as details: except IOError as details:
error_msg = "%s : %s" % (details.strerror, details.filename) error_msg = "%s : %s" % (details.strerror, details.filename)
logging.getLogger("avocado.app").error(error_msg) LOG_UI.error(error_msg)
if args.subcommand == 'run': if args.subcommand == 'run':
sys.exit(exit_codes.AVOCADO_JOB_FAIL) sys.exit(exit_codes.AVOCADO_JOB_FAIL)
else: else:
......
import logging
import smtplib import smtplib
from email.mime.text import MIMEText from email.mime.text import MIMEText
from avocado.core.output import LOG_UI
from avocado.core.settings import settings from avocado.core.settings import settings
from avocado.core.plugin_interfaces import JobPre, JobPost from avocado.core.plugin_interfaces import JobPre, JobPost
...@@ -12,7 +12,6 @@ class Mail(JobPre, JobPost): ...@@ -12,7 +12,6 @@ class Mail(JobPre, JobPost):
description = 'Sends mail to notify on job start/end' description = 'Sends mail to notify on job start/end'
def __init__(self): def __init__(self):
self.log = logging.getLogger("avocado.app")
self.rcpt = settings.get_value(section="plugins.job.mail", self.rcpt = settings.get_value(section="plugins.job.mail",
key="recipient", key="recipient",
key_type=str, key_type=str,
...@@ -46,7 +45,7 @@ class Mail(JobPre, JobPost): ...@@ -46,7 +45,7 @@ class Mail(JobPre, JobPost):
smtp.sendmail(self.sender, [self.rcpt], msg.as_string()) smtp.sendmail(self.sender, [self.rcpt], msg.as_string())
smtp.quit() smtp.quit()
except: except:
self.log.error("Failure to send email notification: " LOG_UI.error("Failure to send email notification: "
"please check your mail configuration") "please check your mail configuration")
pre = post = mail pre = post = mail
import time import time
import logging
from avocado.core.output import LOG_UI
from avocado.core.settings import settings from avocado.core.settings import settings
from avocado.core.plugin_interfaces import JobPre, JobPost from avocado.core.plugin_interfaces import JobPre, JobPost
...@@ -11,7 +11,6 @@ class Sleep(JobPre, JobPost): ...@@ -11,7 +11,6 @@ class Sleep(JobPre, JobPost):
description = 'Sleeps for a number of seconds' description = 'Sleeps for a number of seconds'
def __init__(self): def __init__(self):
self.log = logging.getLogger("avocado.app")
self.seconds = settings.get_value(section="plugins.job.sleep", self.seconds = settings.get_value(section="plugins.job.sleep",
key="seconds", key="seconds",
key_type=int, key_type=int,
...@@ -19,7 +18,7 @@ class Sleep(JobPre, JobPost): ...@@ -19,7 +18,7 @@ class Sleep(JobPre, JobPost):
def sleep(self, job): def sleep(self, job):
for i in xrange(1, self.seconds + 1): for i in xrange(1, self.seconds + 1):
self.log.info("Sleeping %2i/%s", i, self.seconds) LOG_UI.info("Sleeping %2i/%s", i, self.seconds)
time.sleep(1) time.sleep(1)
pre = post = sleep pre = post = sleep
...@@ -27,6 +27,7 @@ import pkg_resources ...@@ -27,6 +27,7 @@ import pkg_resources
import pystache import pystache
from avocado.core import exit_codes from avocado.core import exit_codes
from avocado.core.output import LOG_UI
from avocado.core.plugin_interfaces import CLI, Result from avocado.core.plugin_interfaces import CLI, Result
...@@ -258,15 +259,14 @@ class HTMLResult(Result): ...@@ -258,15 +259,14 @@ class HTMLResult(Result):
report_contents = v.render('utf8') report_contents = v.render('utf8')
except UnicodeDecodeError as details: except UnicodeDecodeError as details:
# FIXME: Remove me when UnicodeDecodeError problem is fixed # FIXME: Remove me when UnicodeDecodeError problem is fixed
import logging LOG_UI.critical("\n" + ("-" * 80))
ui = logging.getLogger("avocado.app") LOG_UI.critical("HTML failed to render the template: %s\n\n",
ui.critical("\n" + ("-" * 80)) template)
ui.critical("HTML failed to render the template: %s\n\n", LOG_UI.critical("-" * 80)
template) LOG_UI.critical("%s:\n\n", details)
ui.critical("-" * 80) LOG_UI.critical("%r", getattr(details, "object",
ui.critical("%s:\n\n", details) "object not found"))
ui.critical("%r", getattr(details, "object", "object not found")) LOG_UI.critical("-" * 80)
ui.critical("-" * 80)
raise raise
self._copy_static_resources(output_path) self._copy_static_resources(output_path)
...@@ -289,8 +289,7 @@ class HTMLResult(Result): ...@@ -289,8 +289,7 @@ class HTMLResult(Result):
html_path = os.path.join(html_dir, 'results.html') html_path = os.path.join(html_dir, 'results.html')
self._render(result, html_path) self._render(result, html_path)
if getattr(job.args, 'stdout_claimed_by', None) is None: if getattr(job.args, 'stdout_claimed_by', None) is None:
log = logging.getLogger("avocado.app") LOG_UI.info("JOB HTML : %s", html_path)
log.info("JOB HTML : %s", html_path)
if open_browser: if open_browser:
self._open_browser(html_path) self._open_browser(html_path)
open_browser = False open_browser = False
...@@ -345,7 +344,6 @@ class HTML(CLI): ...@@ -345,7 +344,6 @@ class HTML(CLI):
def run(self, args): def run(self, args):
if 'html_output' in args and args.html_output == '-': if 'html_output' in args and args.html_output == '-':
log = logging.getLogger("avocado.app") LOG_UI.error('HTML to stdout not supported (not all HTML resources'
log.error('HTML to stdout not supported (not all HTML resources ' ' can be embedded on a single file)')
'can be embedded on a single file)')
sys.exit(exit_codes.AVOCADO_JOB_FAIL) sys.exit(exit_codes.AVOCADO_JOB_FAIL)
...@@ -33,6 +33,7 @@ from avocado.core import exit_codes ...@@ -33,6 +33,7 @@ from avocado.core import exit_codes
from avocado.core import loader from avocado.core import loader
from avocado.core import output from avocado.core import output
from avocado.core import status from avocado.core import status
from avocado.core.output import LOG_JOB, LOG_UI
from avocado.core.plugin_interfaces import CLI from avocado.core.plugin_interfaces import CLI
from avocado.core.runner import TestRunner from avocado.core.runner import TestRunner
from avocado.core.settings import settings from avocado.core.settings import settings
...@@ -491,7 +492,7 @@ class RemoteTestRunner(TestRunner): ...@@ -491,7 +492,7 @@ class RemoteTestRunner(TestRunner):
raise exceptions.JobError('Remote machine does not seem to' raise exceptions.JobError('Remote machine does not seem to'
' have avocado installed') ' have avocado installed')
except Exception as details: except Exception as details:
stacktrace.log_exc_info(sys.exc_info(), logger='avocado.test') stacktrace.log_exc_info(sys.exc_info(), logger=LOG_JOB)
raise exceptions.JobError(details) raise exceptions.JobError(details)
results = self.run_test(self.job.references, timeout) results = self.run_test(self.job.references, timeout)
remote_log_dir = os.path.dirname(results['debuglog']) remote_log_dir = os.path.dirname(results['debuglog'])
...@@ -538,7 +539,7 @@ class RemoteTestRunner(TestRunner): ...@@ -538,7 +539,7 @@ class RemoteTestRunner(TestRunner):
try: try:
self.tear_down() self.tear_down()
except Exception as details: except Exception as details:
stacktrace.log_exc_info(sys.exc_info(), logger='avocado.test') stacktrace.log_exc_info(sys.exc_info(), logger=LOG_JOB)
raise exceptions.JobError(details) raise exceptions.JobError(details)
sys.stdout = stdout_backup sys.stdout = stdout_backup
sys.stderr = stderr_backup sys.stderr = stderr_backup
...@@ -616,10 +617,9 @@ class RemoteCLI(CLI): ...@@ -616,10 +617,9 @@ class RemoteCLI(CLI):
if not getattr(args, arg): if not getattr(args, arg):
missing.append(arg) missing.append(arg)
if missing: if missing:
log = logging.getLogger("avocado.app") LOG_UI.error("Use of %s requires %s arguments to be set. Please "
log.error("Use of %s requires %s arguments to be set. Please set " "set %s.", enable_arg, ', '.join(required_args),
"%s.", enable_arg, ', '.join(required_args), ', '.join(missing))
', '.join(missing))
return sys.exit(exit_codes.AVOCADO_FAIL) return sys.exit(exit_codes.AVOCADO_FAIL)
return True return True
......
...@@ -22,6 +22,7 @@ from xml.dom import minidom ...@@ -22,6 +22,7 @@ from xml.dom import minidom
import libvirt import libvirt
from avocado.core import exit_codes, exceptions from avocado.core import exit_codes, exceptions
from avocado.core.output import LOG_UI
from avocado.core.plugin_interfaces import CLI from avocado.core.plugin_interfaces import CLI
from avocado_runner_remote import Remote, RemoteTestRunner from avocado_runner_remote import Remote, RemoteTestRunner
...@@ -491,10 +492,9 @@ class VMCLI(CLI): ...@@ -491,10 +492,9 @@ class VMCLI(CLI):
if not getattr(args, arg): if not getattr(args, arg):
missing.append(arg) missing.append(arg)
if missing: if missing:
log = logging.getLogger("avocado.app") LOG_UI.error("Use of %s requires %s arguments to be set. Please "
log.error("Use of %s requires %s arguments to be set. Please set " "set %s.", enable_arg, ', '.join(required_args),
"%s.", enable_arg, ', '.join(required_args), ', '.join(missing))
', '.join(missing))
return sys.exit(exit_codes.AVOCADO_FAIL) return sys.exit(exit_codes.AVOCADO_FAIL)
return True return True
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册