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.
|
# limitations under the License.
|
||||||
|
|
||||||
from ghp.errors import HpgitError
|
from ghp.errors import HpgitError
|
||||||
|
from ghp.log import LogDedentMixin
|
||||||
from ghp import subcommand, log
|
from ghp import subcommand, log
|
||||||
|
|
||||||
from git import Repo, GitCommandError
|
from git import Repo, GitCommandError
|
||||||
|
|
||||||
import inspect
|
import inspect
|
||||||
import os
|
import os
|
||||||
import textwrap
|
|
||||||
|
|
||||||
|
|
||||||
class ImportUpstreamError(HpgitError):
|
class ImportUpstreamError(HpgitError):
|
||||||
@@ -29,7 +29,7 @@ class ImportUpstreamError(HpgitError):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ImportUpstream(object):
|
class ImportUpstream(LogDedentMixin):
|
||||||
"""
|
"""
|
||||||
Import code from an upstream project and merge in additional branches
|
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
|
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._repo = Repo(os.environ.get('GIT_WORK_TREE', os.path.curdir))
|
||||||
self._git = self.repo.git
|
self._git = self.repo.git
|
||||||
|
|
||||||
|
# make sure to correctly initialise inherited objects before performing
|
||||||
|
# any computation
|
||||||
|
super(ImportUpstream, self).__init__()
|
||||||
|
|
||||||
if self.repo.bare:
|
if self.repo.bare:
|
||||||
raise ImportUpstreamError("Cannot perform imports in bare repos")
|
raise ImportUpstreamError("Cannot perform imports in bare repos")
|
||||||
|
|
||||||
@@ -142,10 +146,10 @@ class ImportUpstream(object):
|
|||||||
"from '%s' (%s)", self.import_branch, self.upstream, commit)
|
"from '%s' (%s)", self.import_branch, self.upstream, commit)
|
||||||
|
|
||||||
self.log.info(
|
self.log.info(
|
||||||
textwrap.dedent("""\
|
"""\
|
||||||
Checking if import branch '%s' already exists:
|
Checking if import branch '%s' already exists:
|
||||||
git branch --list %s
|
git branch --list %s
|
||||||
"""), self.import_branch, self.import_branch)
|
""", self.import_branch, self.import_branch)
|
||||||
if self.git.show_ref("refs/heads/" + self.import_branch, verify=True,
|
if self.git.show_ref("refs/heads/" + self.import_branch, verify=True,
|
||||||
with_exceptions=False) and not force:
|
with_exceptions=False) and not force:
|
||||||
msg = "Import branch '%s' already exists, use force to replace"
|
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:
|
if self.repo.active_branch == self.import_branch:
|
||||||
self.log.info(
|
self.log.info(
|
||||||
textwrap.dedent(
|
|
||||||
"""\
|
"""\
|
||||||
Resetting import branch '%s' to specified commit '%s'
|
Resetting import branch '%s' to specified commit '%s'
|
||||||
git reset --hard %s
|
git reset --hard %s
|
||||||
"""), self.import_branch, commit, commit)
|
""", self.import_branch, commit, commit)
|
||||||
self.git.reset(commit, hard=True)
|
self.git.reset(commit, hard=True)
|
||||||
elif checkout:
|
elif checkout:
|
||||||
checkout_args = dict(b=True)
|
checkout_args = dict(b=True)
|
||||||
@@ -166,30 +169,27 @@ class ImportUpstream(object):
|
|||||||
checkout_args = dict(B=True)
|
checkout_args = dict(B=True)
|
||||||
|
|
||||||
self.log.info(
|
self.log.info(
|
||||||
textwrap.dedent(
|
|
||||||
"""\
|
"""\
|
||||||
Checking out import branch '%s' using specified commit '%s'
|
Checking out import branch '%s' using specified commit '%s'
|
||||||
git checkout %s %s %s
|
git checkout %s %s %s
|
||||||
"""), self.import_branch, commit, checkout_args,
|
""", self.import_branch, commit, checkout_args,
|
||||||
self.import_branch, commit)
|
self.import_branch, commit)
|
||||||
self.git.checkout(self.import_branch, commit, **checkout_args)
|
self.git.checkout(self.import_branch, commit, **checkout_args)
|
||||||
else:
|
else:
|
||||||
self.log.info(
|
self.log.info(
|
||||||
textwrap.dedent(
|
|
||||||
"""\
|
"""\
|
||||||
Creating import branch '%s' from specified commit '%s'
|
Creating import branch '%s' from specified commit '%s'
|
||||||
git branch --force %s %s
|
git branch --force %s %s
|
||||||
"""), self.import_branch, commit, self.import_branch, commit)
|
""", self.import_branch, commit, self.import_branch, commit)
|
||||||
self.git.branch(self.import_branch, commit, force=force)
|
self.git.branch(self.import_branch, commit, force=force)
|
||||||
|
|
||||||
if self.extra_branches:
|
if self.extra_branches:
|
||||||
self.log.info(
|
self.log.info(
|
||||||
textwrap.dedent(
|
|
||||||
"""\
|
"""\
|
||||||
Merging additional branch(es) '%s' into import branch '%s'
|
Merging additional branch(es) '%s' into import branch '%s'
|
||||||
git checkout %s
|
git checkout %s
|
||||||
git merge %s
|
git merge %s
|
||||||
"""), ", ".join(self.extra_branches), self.import_branch,
|
""", ", ".join(self.extra_branches), self.import_branch,
|
||||||
self.import_branch, " ".join(self.extra_branches))
|
self.import_branch, " ".join(self.extra_branches))
|
||||||
self.git.checkout(self.import_branch)
|
self.git.checkout(self.import_branch)
|
||||||
self.git.merge(*self.extra_branches)
|
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
|
import logging
|
||||||
|
from functools import wraps
|
||||||
|
import textwrap
|
||||||
|
|
||||||
|
|
||||||
# Add new NOTICE logging level
|
# Add new NOTICE logging level
|
||||||
@@ -87,3 +89,63 @@ class LevelFilterIgnoreBelow(logging.Filter):
|
|||||||
|
|
||||||
def filter(self, record):
|
def filter(self, record):
|
||||||
return record.levelno >= self.level
|
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