[CalendarServer-changes] [11380] CalendarServer/trunk/twext/python
source_changes at macosforge.org
source_changes at macosforge.org
Wed Jun 19 12:18:47 PDT 2013
Revision: 11380
http://trac.calendarserver.org//changeset/11380
Author: wsanchez at apple.com
Date: 2013-06-19 12:18:47 -0700 (Wed, 19 Jun 2013)
Log Message:
-----------
LegacyLogger no longer inherrits from Logger.
LegacyLogger passes attribute access up to twisted.python.log.
Add replaceTwistedLoggers.
Modified Paths:
--------------
CalendarServer/trunk/twext/python/log.py
CalendarServer/trunk/twext/python/test/test_log.py
Modified: CalendarServer/trunk/twext/python/log.py
===================================================================
--- CalendarServer/trunk/twext/python/log.py 2013-06-18 00:44:18 UTC (rev 11379)
+++ CalendarServer/trunk/twext/python/log.py 2013-06-19 19:18:47 UTC (rev 11380)
@@ -67,9 +67,11 @@
"FilteringLogObserver",
"LogLevelFilterPredicate",
"LegacyLogObserver",
+ "replaceTwistedLoggers",
#"StandardIOObserver",
]
+import sys
from sys import stdout, stderr
from string import Formatter
import inspect
@@ -80,6 +82,7 @@
from twisted.python.constants import NamedConstant, Names
from twisted.python.failure import Failure
from twisted.python.reflect import safe_str
+import twisted.python.log
from twisted.python.log import msg as twistedLogMessage
from twisted.python.log import addObserver, removeObserver
from twisted.python.log import ILogObserver as ILegacyLogObserver
@@ -237,6 +240,16 @@
publisher = lambda e: None
+ @staticmethod
+ def _namespaceFromCallingContext():
+ """
+ Derive a namespace from the module containing the caller's caller.
+
+ @return: a namespace
+ """
+ return inspect.currentframe().f_back.f_back.f_globals["__name__"]
+
+
def __init__(self, namespace=None, source=None):
"""
@param namespace: The namespace for this logger. Uses a dotted
@@ -248,12 +261,8 @@
if this L{Logger} is an attribute of that class.
"""
if namespace is None:
- currentFrame = inspect.currentframe()
- callerFrame = currentFrame.f_back
- callerModule = callerFrame.f_globals["__name__"]
+ namespace = self._namespaceFromCallingContext()
- namespace = callerModule
-
self.namespace = namespace
self.source = source
@@ -265,11 +274,17 @@
# athing.py
class Something(object):
log = Logger()
- def something(self):
+ def hello(self):
self.log.info("Hello")
a L{Logger}'s namespace will be set to the name of the class it is
- declared on, in this case, C{athing.Something}.
+ declared on. In the above example, the namespace would be
+ C{athing.Something}.
+
+ Additionally, it's source will be set to the actual object referring to
+ the L{Logger}. In the above example, C{Something.log.source} would be
+ C{Something}, and C{Something().log.source} would be an instance of
+ C{Something}.
"""
if oself is None:
source = type
@@ -358,12 +373,26 @@
-class LegacyLogger(Logger):
+class LegacyLogger(object):
"""
- A L{Logger} that provides some compatibility with the L{twisted.python.log}
- module.
+ A logging object that provides some compatibility with the
+ L{twisted.python.log} module.
"""
+ def __init__(self, logger=None):
+ if logger is not None:
+ self.newStyleLogger = logger
+ else:
+ self.newStyleLogger = Logger(Logger._namespaceFromCallingContext())
+
+
+ def __getattribute__(self, name):
+ try:
+ return super(LegacyLogger, self).__getattribute__(name)
+ except AttributeError:
+ return getattr(twisted.python.log, name)
+
+
def msg(self, *message, **kwargs):
"""
This method is API-compatible with L{twisted.python.log.msg} and exists
@@ -373,7 +402,7 @@
message = " ".join(map(safe_str, message))
else:
message = None
- return self.emit(LogLevel.info, message, **kwargs)
+ return self.newStyleLogger.emit(LogLevel.info, message, **kwargs)
def err(self, _stuff=None, _why=None, **kwargs):
@@ -387,10 +416,10 @@
_stuff = Failure(_stuff)
if isinstance(_stuff, Failure):
- self.emit(LogLevel.error, failure=_stuff, why=_why, isError=1, **kwargs)
+ self.newStyleLogger.emit(LogLevel.error, failure=_stuff, why=_why, isError=1, **kwargs)
else:
# We got called with an invalid _stuff.
- self.emit(LogLevel.error, repr(_stuff), why=_why, isError=1, **kwargs)
+ self.newStyleLogger.emit(LogLevel.error, repr(_stuff), why=_why, isError=1, **kwargs)
@@ -811,7 +840,46 @@
theFormatter = Formatter()
+def replaceTwistedLoggers():
+ """
+ Visit all Python modules that have been loaded and:
+ - replace L{twisted.python.log} with a L{LegacyLogger}
+
+ - replace L{twisted.python.log.msg} with a L{LegacyLogger}'s C{msg}
+
+ - replace L{twisted.python.log.err} with a L{LegacyLogger}'s C{err}
+ """
+ log = Logger()
+
+ for moduleName, module in sys.modules.iteritems():
+ # Oddly, this happens
+ if module is None:
+ continue
+
+ # Don't patch Twisted's logging module
+ if module in (twisted.python, twisted.python.log):
+ continue
+
+ # Don't patch this module
+ if moduleName is __name__:
+ continue
+
+ for name, obj in module.__dict__.iteritems():
+ legacyLogger = LegacyLogger(logger=Logger(namespace=module.__name__))
+
+ if obj is twisted.python.log:
+ log.info("Replacing Twisted log module object {0} in {1}".format(name, module.__name__))
+ setattr(module, name, legacyLogger)
+ elif obj is twisted.python.log.msg:
+ log.info("Replacing Twisted log.msg object {0} in {1}".format(name, module.__name__))
+ setattr(module, name, legacyLogger.msg)
+ elif obj is twisted.python.log.err:
+ log.info("Replacing Twisted log.err object {0} in {1}".format(name, module.__name__))
+ setattr(module, name, legacyLogger.err)
+
+
+
######################################################################
# FIXME: This may not be needed; look into removing it.
Modified: CalendarServer/trunk/twext/python/test/test_log.py
===================================================================
--- CalendarServer/trunk/twext/python/test/test_log.py 2013-06-18 00:44:18 UTC (rev 11379)
+++ CalendarServer/trunk/twext/python/test/test_log.py 2013-06-19 19:18:47 UTC (rev 11380)
@@ -39,7 +39,7 @@
-class TestLoggerMixIn(object):
+class TestLogger(Logger):
def emit(self, level, format=None, **kwargs):
if False:
print "*"*60
@@ -66,16 +66,12 @@
-class TestLogger(TestLoggerMixIn, Logger):
- pass
+class TestLegacyLogger(LegacyLogger):
+ def __init__(self):
+ LegacyLogger.__init__(self, logger=TestLogger())
-class TestLegacyLogger(TestLoggerMixIn, LegacyLogger):
- pass
-
-
-
class LogComposedObject(object):
"""
Just a regular object.
@@ -601,6 +597,21 @@
Tests for L{LegacyLogger}.
"""
+ def test_passThroughAttributes(self):
+ """
+ C{__getattribute__} on L{LegacyLogger} is passing through to Twisted's
+ logging module.
+ """
+ log = TestLegacyLogger()
+
+ # Not passed through
+ self.assertIn("API-compatible", log.msg.__doc__)
+ self.assertIn("API-compatible", log.err.__doc__)
+
+ # Passed through
+ self.assertIdentical(log.addObserver, twistedLogging.addObserver)
+
+
def test_legacy_msg(self):
"""
Test LegacyLogger's log.msg()
@@ -612,16 +623,16 @@
log.msg(message, **kwargs)
- self.assertIdentical(log.emitted["level"], LogLevel.info)
- self.assertEquals(log.emitted["format"], message)
+ self.assertIdentical(log.newStyleLogger.emitted["level"], LogLevel.info)
+ self.assertEquals(log.newStyleLogger.emitted["format"], message)
for key, value in kwargs.items():
- self.assertIdentical(log.emitted["kwargs"][key], value)
+ self.assertIdentical(log.newStyleLogger.emitted["kwargs"][key], value)
log.msg(foo="")
- self.assertIdentical(log.emitted["level"], LogLevel.info)
- self.assertIdentical(log.emitted["format"], None)
+ self.assertIdentical(log.newStyleLogger.emitted["level"], LogLevel.info)
+ self.assertIdentical(log.newStyleLogger.emitted["format"], None)
def test_legacy_err_implicit(self):
@@ -696,12 +707,12 @@
errors = self.flushLoggedErrors(exception.__class__)
self.assertEquals(len(errors), 0)
- self.assertIdentical(log.emitted["level"], LogLevel.error)
- self.assertEquals(log.emitted["format"], repr(bogus))
- self.assertIdentical(log.emitted["kwargs"]["why"], why)
+ self.assertIdentical(log.newStyleLogger.emitted["level"], LogLevel.error)
+ self.assertEquals(log.newStyleLogger.emitted["format"], repr(bogus))
+ self.assertIdentical(log.newStyleLogger.emitted["kwargs"]["why"], why)
for key, value in kwargs.items():
- self.assertIdentical(log.emitted["kwargs"][key], value)
+ self.assertIdentical(log.newStyleLogger.emitted["kwargs"][key], value)
def legacy_err(self, log, kwargs, why, exception):
@@ -713,11 +724,11 @@
errors = self.flushLoggedErrors(exception.__class__)
self.assertEquals(len(errors), 1)
- self.assertIdentical(log.emitted["level"], LogLevel.error)
- self.assertEquals(log.emitted["format"], None)
- self.assertIdentical(log.emitted["kwargs"]["failure"].__class__, Failure)
- self.assertIdentical(log.emitted["kwargs"]["failure"].value, exception)
- self.assertIdentical(log.emitted["kwargs"]["why"], why)
+ self.assertIdentical(log.newStyleLogger.emitted["level"], LogLevel.error)
+ self.assertEquals(log.newStyleLogger.emitted["format"], None)
+ self.assertIdentical(log.newStyleLogger.emitted["kwargs"]["failure"].__class__, Failure)
+ self.assertIdentical(log.newStyleLogger.emitted["kwargs"]["failure"].value, exception)
+ self.assertIdentical(log.newStyleLogger.emitted["kwargs"]["why"], why)
for key, value in kwargs.items():
- self.assertIdentical(log.emitted["kwargs"][key], value)
+ self.assertIdentical(log.newStyleLogger.emitted["kwargs"][key], value)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20130619/0e93d358/attachment-0001.html>
More information about the calendarserver-changes
mailing list