Create a logging mixin class that auto dedents log messages
Construct a metaclass that can be used to create subclasses of the logging.Logger class which wraps all methods for logging output with a function that initially dedents the message. Change-Id: Ice5dd54dbdeabb086115953d30369dd933c7a374
This commit is contained in:
@@ -15,13 +15,13 @@
|
||||
# limitations under the License.
|
||||
|
||||
from ghp.errors import HpgitError
|
||||
from ghp.log import LogDedentMixin
|
||||
from ghp import subcommand, log
|
||||
|
||||
from git import Repo, GitCommandError
|
||||
|
||||
import inspect
|
||||
import os
|
||||
import textwrap
|
||||
|
||||
|
||||
class ImportUpstreamError(HpgitError):
|
||||
@@ -29,7 +29,7 @@ class ImportUpstreamError(HpgitError):
|
||||
pass
|
||||
|
||||
|
||||
class ImportUpstream(object):
|
||||
class ImportUpstream(LogDedentMixin):
|
||||
"""
|
||||
Import code from an upstream project and merge in additional branches
|
||||
to create a new branch unto which changes that are not upstream but are
|
||||
@@ -46,6 +46,10 @@ class ImportUpstream(object):
|
||||
self._repo = Repo(os.environ.get('GIT_WORK_TREE', os.path.curdir))
|
||||
self._git = self.repo.git
|
||||
|
||||
# make sure to correctly initialise inherited objects before performing
|
||||
# any computation
|
||||
super(ImportUpstream, self).__init__()
|
||||
|
||||
if self.repo.bare:
|
||||
raise ImportUpstreamError("Cannot perform imports in bare repos")
|
||||
|
||||
@@ -142,10 +146,10 @@ class ImportUpstream(object):
|
||||
"from '%s' (%s)", self.import_branch, self.upstream, commit)
|
||||
|
||||
self.log.info(
|
||||
textwrap.dedent("""\
|
||||
Checking if import branch '%s' already exists:
|
||||
git branch --list %s
|
||||
"""), self.import_branch, self.import_branch)
|
||||
"""\
|
||||
Checking if import branch '%s' already exists:
|
||||
git branch --list %s
|
||||
""", self.import_branch, self.import_branch)
|
||||
if self.git.show_ref("refs/heads/" + self.import_branch, verify=True,
|
||||
with_exceptions=False) and not force:
|
||||
msg = "Import branch '%s' already exists, use force to replace"
|
||||
@@ -154,11 +158,10 @@ class ImportUpstream(object):
|
||||
|
||||
if self.repo.active_branch == self.import_branch:
|
||||
self.log.info(
|
||||
textwrap.dedent(
|
||||
"""\
|
||||
Resetting import branch '%s' to specified commit '%s'
|
||||
git reset --hard %s
|
||||
"""), self.import_branch, commit, commit)
|
||||
"""\
|
||||
Resetting import branch '%s' to specified commit '%s'
|
||||
git reset --hard %s
|
||||
""", self.import_branch, commit, commit)
|
||||
self.git.reset(commit, hard=True)
|
||||
elif checkout:
|
||||
checkout_args = dict(b=True)
|
||||
@@ -166,30 +169,27 @@ class ImportUpstream(object):
|
||||
checkout_args = dict(B=True)
|
||||
|
||||
self.log.info(
|
||||
textwrap.dedent(
|
||||
"""\
|
||||
Checking out import branch '%s' using specified commit '%s'
|
||||
git checkout %s %s %s
|
||||
"""), self.import_branch, commit, checkout_args,
|
||||
"""\
|
||||
Checking out import branch '%s' using specified commit '%s'
|
||||
git checkout %s %s %s
|
||||
""", self.import_branch, commit, checkout_args,
|
||||
self.import_branch, commit)
|
||||
self.git.checkout(self.import_branch, commit, **checkout_args)
|
||||
else:
|
||||
self.log.info(
|
||||
textwrap.dedent(
|
||||
"""\
|
||||
Creating import branch '%s' from specified commit '%s'
|
||||
git branch --force %s %s
|
||||
"""), self.import_branch, commit, self.import_branch, commit)
|
||||
"""\
|
||||
Creating import branch '%s' from specified commit '%s'
|
||||
git branch --force %s %s
|
||||
""", self.import_branch, commit, self.import_branch, commit)
|
||||
self.git.branch(self.import_branch, commit, force=force)
|
||||
|
||||
if self.extra_branches:
|
||||
self.log.info(
|
||||
textwrap.dedent(
|
||||
"""\
|
||||
Merging additional branch(es) '%s' into import branch '%s'
|
||||
git checkout %s
|
||||
git merge %s
|
||||
"""), ", ".join(self.extra_branches), self.import_branch,
|
||||
"""\
|
||||
Merging additional branch(es) '%s' into import branch '%s'
|
||||
git checkout %s
|
||||
git merge %s
|
||||
""", ", ".join(self.extra_branches), self.import_branch,
|
||||
self.import_branch, " ".join(self.extra_branches))
|
||||
self.git.checkout(self.import_branch)
|
||||
self.git.merge(*self.extra_branches)
|
||||
|
62
ghp/log.py
62
ghp/log.py
@@ -24,6 +24,8 @@ for logging output to the console.
|
||||
"""
|
||||
|
||||
import logging
|
||||
from functools import wraps
|
||||
import textwrap
|
||||
|
||||
|
||||
# Add new NOTICE logging level
|
||||
@@ -87,3 +89,63 @@ class LevelFilterIgnoreBelow(logging.Filter):
|
||||
|
||||
def filter(self, record):
|
||||
return record.levelno >= self.level
|
||||
|
||||
|
||||
class DedentLoggerMeta(type):
|
||||
"""
|
||||
Meta class to wrap all level functions in logging interface with dedent
|
||||
|
||||
Classes created from this should be derived from the logging.Logger class
|
||||
as otherwise they will not contain the correct methods to be wrapped and
|
||||
trying to pass them as the default class to create Loggers from will fail.
|
||||
"""
|
||||
|
||||
def __new__(cls, name, bases, dict):
|
||||
# provide a more intelligent error instead of waiting for setattr/getattr
|
||||
# adding of a wrapper function to fail
|
||||
if logging.Logger not in bases:
|
||||
raise TypeError("%s not derived from logging.Logger" % name)
|
||||
|
||||
obj = super(DedentLoggerMeta, cls).__new__(cls, name, bases, dict)
|
||||
for level in _levels:
|
||||
setattr(obj, level, cls.wrap_level(getattr(obj, level)))
|
||||
setattr(obj, 'log', cls.wrap(getattr(obj, 'log')))
|
||||
return obj
|
||||
|
||||
@staticmethod
|
||||
def wrap(func):
|
||||
def _dedent_log(self, level, msg, *args, **kwargs):
|
||||
dedent = kwargs.pop('dedent', True)
|
||||
if dedent:
|
||||
msg = textwrap.dedent(msg)
|
||||
func(self, level, msg, *args, **kwargs)
|
||||
return wraps(func)(_dedent_log)
|
||||
|
||||
@staticmethod
|
||||
def wrap_level(func):
|
||||
def _dedent_log(self, msg, *args, **kwargs):
|
||||
dedent = kwargs.pop('dedent', True)
|
||||
if dedent:
|
||||
msg = textwrap.dedent(msg)
|
||||
func(self, msg, *args, **kwargs)
|
||||
return wraps(func)(_dedent_log)
|
||||
|
||||
|
||||
class DedentLogger(logging.Logger):
|
||||
__metaclass__ = DedentLoggerMeta
|
||||
|
||||
|
||||
# override default logger class for everything that imports this module
|
||||
logging.setLoggerClass(DedentLogger)
|
||||
|
||||
|
||||
class LogDedentMixin(object):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.__log = getLogger('%s.%s' % (__name__, self.__class__.__name__))
|
||||
|
||||
super(LogDedentMixin, self).__init__(*args, **kwargs)
|
||||
|
||||
@property
|
||||
def log(self):
|
||||
return self.__log
|
||||
|
Reference in New Issue
Block a user