From cca1d20b0e7ce85bba6ed9832d4b158fe2e422bb Mon Sep 17 00:00:00 2001 From: Cosimo Lupo Date: Tue, 11 Apr 2017 18:40:52 +0100 Subject: [PATCH 1/2] [loggingTools] added LogMixin class This is useful to quickly add logging functionality to classes, and to reduce boilerplate. It adds a 'log' property to the class inheriting from it, which uses logging.getLogger to get a logging.Logger (sigleton) object named after . of self. --- Lib/fontTools/misc/loggingTools.py | 12 ++++++++++++ Lib/fontTools/ttLib/tables/T_S_I__1.py | 8 ++------ Tests/misc/loggingTools_test.py | 24 +++++++++++++++++++++++- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/Lib/fontTools/misc/loggingTools.py b/Lib/fontTools/misc/loggingTools.py index 9345716f2..de9a87a38 100644 --- a/Lib/fontTools/misc/loggingTools.py +++ b/Lib/fontTools/misc/loggingTools.py @@ -471,6 +471,18 @@ class CapturingLogHandler(logging.Handler): return True assert 0, "Pattern '%s' not found in logger records" % regexp + +class LogMixin(object): + """ Mixin class that adds a 'log' property getter returning an instance + of logging.Logger class, which is named after self . name. + """ + + @property + def log(self): + name = ".".join([self.__class__.__module__, self.__class__.__name__]) + return logging.getLogger(name) + + def deprecateArgument(name, msg, category=UserWarning): """ Raise a warning about deprecated function argument 'name'. """ warnings.warn( diff --git a/Lib/fontTools/ttLib/tables/T_S_I__1.py b/Lib/fontTools/ttLib/tables/T_S_I__1.py index a80d27a05..497d3afe0 100644 --- a/Lib/fontTools/ttLib/tables/T_S_I__1.py +++ b/Lib/fontTools/ttLib/tables/T_S_I__1.py @@ -7,19 +7,15 @@ code, as well as the 'extra' programs 'fpgm', 'ppgm' (i.e. 'prep'), and 'cvt'. from __future__ import print_function, division, absolute_import from fontTools.misc.py23 import * from . import DefaultTable -import logging +from fontTools.misc.loggingTools import LogMixin -class table_T_S_I__1(DefaultTable.DefaultTable): +class table_T_S_I__1(LogMixin, DefaultTable.DefaultTable): extras = {0xfffa: "ppgm", 0xfffb: "cvt", 0xfffc: "reserved", 0xfffd: "fpgm"} indextable = "TSI0" - def __init__(self, tag=None): - super(table_T_S_I__1, self).__init__(tag) - self.log = logging.getLogger(self.__class__.__module__) - def decompile(self, data, ttFont): totalLength = len(data) indextable = ttFont[self.indextable] diff --git a/Tests/misc/loggingTools_test.py b/Tests/misc/loggingTools_test.py index 6e793c062..81ffb8db5 100644 --- a/Tests/misc/loggingTools_test.py +++ b/Tests/misc/loggingTools_test.py @@ -1,7 +1,7 @@ from __future__ import print_function, division, absolute_import from fontTools.misc.py23 import * from fontTools.misc.loggingTools import ( - LevelFormatter, Timer, configLogger, ChannelsFilter) + LevelFormatter, Timer, configLogger, ChannelsFilter, LogMixin) import logging import textwrap import time @@ -148,3 +148,25 @@ def test_ChannelsFilter(logger): logging.getLogger(n+'.C.DE').debug('neither this one!') assert before == stream.getvalue() + + +def test_LogMixin(): + + class Base(object): + pass + + class A(LogMixin, Base): + pass + + class B(A): + pass + + a = A() + b = B() + + assert hasattr(a, 'log') + assert hasattr(b, 'log') + assert isinstance(a.log, logging.Logger) + assert isinstance(b.log, logging.Logger) + assert a.log.name == "loggingTools_test.A" + assert b.log.name == "loggingTools_test.B" From 1e31e55682f6f77eca2f0d318b7903fdbeb7b30d Mon Sep 17 00:00:00 2001 From: Cosimo Lupo Date: Wed, 12 Apr 2017 11:20:42 +0100 Subject: [PATCH 2/2] [loggingTools] add docstring to exemplify usage of LogMixin --- Lib/fontTools/misc/loggingTools.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/Lib/fontTools/misc/loggingTools.py b/Lib/fontTools/misc/loggingTools.py index de9a87a38..4ed788e99 100644 --- a/Lib/fontTools/misc/loggingTools.py +++ b/Lib/fontTools/misc/loggingTools.py @@ -473,8 +473,29 @@ class CapturingLogHandler(logging.Handler): class LogMixin(object): - """ Mixin class that adds a 'log' property getter returning an instance - of logging.Logger class, which is named after self . name. + """ Mixin class that adds logging functionality to another class. + You can define a new class that subclasses from LogMixin as well as + other base classes through multiple inheritance. + All instances of that class will have a 'log' property that returns + a logging.Logger named after their respective .. + For example: + + >>> class BaseClass(object): + ... pass + >>> class MyClass(LogMixin, BaseClass): + ... pass + >>> a = MyClass() + >>> isinstance(a.log, logging.Logger) + True + >>> print(a.log.name) + fontTools.misc.loggingTools.MyClass + >>> class AnotherClass(MyClass): + ... pass + >>> b = AnotherClass() + >>> isinstance(b.log, logging.Logger) + True + >>> print(b.log.name) + fontTools.misc.loggingTools.AnotherClass """ @property