[CalendarServer-changes] [11335] CalendarServer/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Wed Jun 12 13:56:26 PDT 2013
Revision: 11335
http://trac.calendarserver.org//changeset/11335
Author: wsanchez at apple.com
Date: 2013-06-12 13:56:26 -0700 (Wed, 12 Jun 2013)
Log Message:
-----------
Logging methods now take a required format arg instead of a fixed string message optional arg.
log.failure() now requires a format first arg instead of message optional second arg.
eventDict keys added by the logging system now have a "log_" prefix.
Starting to isolate the legacy logging.
Define a new non-legacy ILogObserver.
Modified Paths:
--------------
CalendarServer/trunk/calendarserver/tools/calverify.py
CalendarServer/trunk/calendarserver/tools/export.py
CalendarServer/trunk/calendarserver/tools/migrate_verify.py
CalendarServer/trunk/calendarserver/tools/obliterate.py
CalendarServer/trunk/twext/internet/sendfdport.py
CalendarServer/trunk/twext/python/log.py
CalendarServer/trunk/twext/python/test/test_log.py
CalendarServer/trunk/twext/web2/http.py
CalendarServer/trunk/twext/web2/server.py
CalendarServer/trunk/twext/web2/stream.py
CalendarServer/trunk/twistedcaldav/directory/calendaruserproxyloader.py
CalendarServer/trunk/twistedcaldav/storebridge.py
CalendarServer/trunk/txdav/base/datastore/subpostgres.py
CalendarServer/trunk/txdav/caldav/datastore/scheduling/processing.py
CalendarServer/trunk/txdav/caldav/datastore/util.py
CalendarServer/trunk/txdav/common/datastore/sql.py
CalendarServer/trunk/txdav/common/datastore/test/util.py
Modified: CalendarServer/trunk/calendarserver/tools/calverify.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/calverify.py 2013-06-12 20:36:24 UTC (rev 11334)
+++ CalendarServer/trunk/calendarserver/tools/calverify.py 2013-06-12 20:56:26 UTC (rev 11335)
@@ -426,7 +426,7 @@
yield self.doAction()
self.output.close()
except:
- log.failure()
+ log.failure("doCalVerify()")
self.reactor.stop()
Modified: CalendarServer/trunk/calendarserver/tools/export.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/export.py 2013-06-12 20:36:24 UTC (rev 11334)
+++ CalendarServer/trunk/calendarserver/tools/export.py 2013-06-12 20:56:26 UTC (rev 11335)
@@ -326,7 +326,7 @@
# update stuff needed to happen, don't want to undo it.
self.output.close()
except:
- log.failure()
+ log.failure("doExport()")
self.reactor.stop()
Modified: CalendarServer/trunk/calendarserver/tools/migrate_verify.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/migrate_verify.py 2013-06-12 20:36:24 UTC (rev 11334)
+++ CalendarServer/trunk/calendarserver/tools/migrate_verify.py 2013-06-12 20:56:26 UTC (rev 11335)
@@ -163,7 +163,7 @@
except ConfigError:
pass
except:
- log.failure()
+ log.failure("doMigrateVerify()")
self.reactor.stop()
Modified: CalendarServer/trunk/calendarserver/tools/obliterate.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/obliterate.py 2013-06-12 20:36:24 UTC (rev 11334)
+++ CalendarServer/trunk/calendarserver/tools/obliterate.py 2013-06-12 20:56:26 UTC (rev 11335)
@@ -186,7 +186,7 @@
except ConfigError:
pass
except:
- log.failure()
+ log.failure("doObliterate()")
self.reactor.stop()
Modified: CalendarServer/trunk/twext/internet/sendfdport.py
===================================================================
--- CalendarServer/trunk/twext/internet/sendfdport.py 2013-06-12 20:36:24 UTC (rev 11334)
+++ CalendarServer/trunk/twext/internet/sendfdport.py 2013-06-12 20:56:26 UTC (rev 11335)
@@ -298,7 +298,7 @@
description, protocol)
protocol.makeConnection(transport)
except:
- log.failure()
+ log.failure("doRead()")
def doWrite(self):
Modified: CalendarServer/trunk/twext/python/log.py
===================================================================
--- CalendarServer/trunk/twext/python/log.py 2013-06-12 20:36:24 UTC (rev 11334)
+++ CalendarServer/trunk/twext/python/log.py 2013-06-12 20:56:26 UTC (rev 11335)
@@ -14,7 +14,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
##
-from __future__ import print_function
"""
Classes and functions to do granular logging.
@@ -24,8 +23,10 @@
from twext.python.log import Logger
log = Logger()
- log.info("Blah blah")
+ ...
+ log.debug("Got data: {data}.", data=data)
+
Or in a class:
from twext.python.log import Logger
@@ -33,8 +34,8 @@
class Foo(object):
log = Logger()
- def oops(self):
- self.log.error("Oops!")
+ def oops(self, data):
+ self.log.error("Oops! Invalid data from server: {data}", data=data)
C{Logger}s have namespaces, for which logging can be configured independently.
Namespaces may be specified by passing in a C{namespace} argument to L{Logger}
@@ -49,7 +50,6 @@
#
# TODO List:
#
-# * Replace message argument with format argument
# * Filter in observers, not emit()
#
@@ -61,6 +61,8 @@
"clearLogLevels",
"Logger",
"LegacyLogger",
+ "ILogObserver",
+ "ILegacyLogObserver",
"StandardIOObserver",
]
@@ -69,6 +71,7 @@
import inspect
import logging
+from zope.interface import Interface
from twisted.python.constants import NamedConstant, Names
from twisted.python.failure import Failure
from twisted.python.reflect import safe_str
@@ -160,7 +163,7 @@
def setLogLevelForNamespace(namespace, level):
"""
- Sets the log level for a logging namespace.
+ Sets the global log level for a logging namespace.
@param namespace: a logging namespace
@@ -177,7 +180,7 @@
def clearLogLevels():
"""
- Clears all log levels to the default.
+ Clears all global log levels to the default.
"""
logLevelsByNamespace.clear()
logLevelsByNamespace[None] = LogLevel.warn # Default log level
@@ -257,17 +260,24 @@
@param kwargs: additional keyword parameters to include with the
message.
"""
- if level not in LogLevel.iterconstants():
- self.failure(Failure(InvalidLogLevelError(level)))
+ if level not in LogLevel.iterconstants(): # FIXME: Updated Twisted supports 'in' on constants container
+ self.failure(
+ "Got invalid log level in {logger}.emit().",
+ Failure(InvalidLogLevelError(level)),
+ logger = self,
+ )
level = LogLevel.error
+ return
# FIXME: Filtering should be done by the log observer(s)
if not self.willLogAtLevel(level):
return
kwargs.update(
- level = level, levelName = level.name,
- namespace = self.namespace, source = self.source,
+ log_level = level,
+ log_levelName = level.name, # FIXME: Remove
+ log_namespace = self.namespace,
+ log_source = self.source,
)
#
@@ -277,19 +287,15 @@
if level in pythonLogLevelMapping:
kwargs["logLevel"] = pythonLogLevelMapping[level]
- prefix = "[%(namespace)s#%(levelName)s] "
+ prefix = "[%(log_namespace)s#%(log_levelName)s] "
- if "failure" in kwargs:
- # Handle unfortunate logic in twisted.log.textFromEventDict()
- # in which format is ignored if we have a failure and no why.
- why = kwargs.get("why", None)
- if not why:
- why = "Unhandled Error"
- kwargs["why"] = "%s%s" % (prefix % kwargs, why)
+ if "log_failure" in kwargs:
+ # FIXME: legacy cruft: failure, isError, why
+ kwargs["failure"] = kwargs["log_failure"]
+ kwargs["isError"] = 1
+ kwargs["why"] = "%s%s" % (prefix % kwargs, format % kwargs)
if format:
- kwargs["log_format"] = format
-
#
# Create an object that implements __str__() in order to
# defer the work of formatting until it's needed by a
@@ -299,16 +305,30 @@
def __str__(self):
return format.format(**kwargs)
- kwargs["format"] = prefix + "%(log_legacy)s"
+ # FIXME: legacy cruft: format
+ # FIXME: Adding the prefix should be the observer's problem
+ kwargs["log_format"] = kwargs["format"] = prefix + "%(log_legacy)s"
kwargs["log_legacy"] = LegacyFormatStub()
twistedLogMessage(**kwargs)
- def failure(self, failure=None, message=None, **kwargs):
+ def failure(self, format, failure=None, **kwargs):
"""
- Log a failure.
+ Log an failure and emit a traceback.
+ For example::
+
+ try:
+ frob(knob)
+ except:
+ log.failure("While frobbing {knob}", knob=knob)
+
+ or::
+
+ d = deferred_frob(knob)
+ d.addErrback(lambda f: log.failure, "While frobbing {knob}", f, knob=knob)
+
@param failure: a L{Failure} to log. If C{None}, a L{Failure} is
created from the exception in flight.
@@ -320,25 +340,26 @@
if failure is None:
failure=Failure()
- self.emit(LogLevel.error, None, failure=failure, isError=1, why=message, **kwargs)
+ self.emit(LogLevel.error, format, log_failure=failure, **kwargs)
def level(self):
"""
- @return: the log level for this logger's namespace.
+ @return: the global log level for this logger's namespace.
"""
return logLevelForNamespace(self.namespace)
def setLevel(self, level):
"""
- Set the log level for this logger's namespace.
+ Set the global log level for this logger's namespace.
@param level: a L{LogLevel}
"""
setLogLevelForNamespace(self.namespace, level)
+ # FIXME: get rid of this
def willLogAtLevel(self, level):
"""
@param level: a L{LogLevel}
@@ -423,6 +444,36 @@
# Observers
#
+class ILogObserver(Interface):
+ """
+ An observer which can handle log events.
+ """
+ def __call__(eventDict):
+ """
+ Log an event.
+
+ @type eventDict: C{dict} with C{str} keys.
+
+ @param eventDict: A dictionary with arbitrary keys as defined
+ by the application emitting logging events, as well as
+ keys added by the logging system, with are:
+ ...
+ """
+
+
+# Import the legacy interface from Twisted
+from twisted.python.log import ILogObserver as ILegacyLogObserver
+
+
+class FilteringLogObserverWrapper(object):
+ """
+ """
+
+
+
+
+# FIXME: This may not be needed; look into removing it.
+
class StandardIOObserver(object):
"""
Log observer that writes to standard I/O.
Modified: CalendarServer/trunk/twext/python/test/test_log.py
===================================================================
--- CalendarServer/trunk/twext/python/test/test_log.py 2013-06-12 20:36:24 UTC (rev 11334)
+++ CalendarServer/trunk/twext/python/test/test_log.py 2013-06-12 20:56:26 UTC (rev 11335)
@@ -14,8 +14,6 @@
# limitations under the License.
##
-import logging
-
from twisted.python import log as twistedLogging
from twisted.python.failure import Failure
@@ -34,23 +32,24 @@
class TestLoggerMixIn(object):
- def emit(self, level, message=None, **kwargs):
+ def emit(self, level, format=None, **kwargs):
def observer(eventDict):
self.eventDict = eventDict
twistedLogging.addObserver(observer)
- Logger.emit(self, level, message, **kwargs)
+ Logger.emit(self, level, format, **kwargs)
twistedLogging.removeObserver(observer)
self.emitted = {
- "level" : level,
- "message": message,
- "kwargs" : kwargs,
+ "level" : level,
+ "format": format,
+ "kwargs": kwargs,
}
+
class TestLogger(TestLoggerMixIn, Logger):
pass
@@ -121,14 +120,14 @@
def test_sourceAvailableForFormatting(self):
"""
- On instances that have a L{Logger} class attribute, the C{source} key
+ On instances that have a L{Logger} class attribute, the C{log_source} key
is available to format strings.
"""
obj = LogComposedObject("hello")
log = obj.log
- log.error("Hello. {source}")
+ log.error("Hello, {log_source}.")
stuff = twistedLogging.textFromEventDict(log.eventDict)
- self.assertIn("Hello. <LogComposedObject hello>", stuff)
+ self.assertIn("Hello, <LogComposedObject hello>.", stuff)
def test_basic_Logger(self):
@@ -136,21 +135,31 @@
Test that log levels and messages are emitted correctly for
Logger.
"""
+ # FIXME:Need a basic test like this for logger attached to a class.
+ # At least: source should not be None in that case.
+
for level in LogLevel.iterconstants():
- message = "This is a {level} message".format(level=level.name)
+ format = "This is a {level_name} message"
+ message = format.format(level_name=level.name)
log = TestLogger()
method = getattr(log, level.name)
- method(message, junk=message)
+ method(format, junk=message, level_name=level.name)
# Ensure that test_emit got called with expected arguments
self.assertEquals(log.emitted["level"], level)
- self.assertEquals(log.emitted["message"], message)
+ self.assertEquals(log.emitted["format"], format)
self.assertEquals(log.emitted["kwargs"]["junk"], message)
if log.willLogAtLevel(level):
- self.assertEquals(log.eventDict["level"], level)
+ #self.assertEquals(log.eventDict["log_format"], format) # FIXME: doesn't work due to emit() mangling the format
+ self.assertEquals(log.eventDict["log_level"], level)
+ self.assertEquals(log.eventDict["log_levelName"], level.name)
+ self.assertEquals(log.eventDict["log_namespace"], __name__)
+ self.assertEquals(log.eventDict["log_source"], None)
+
self.assertEquals(log.eventDict["logLevel"], pythonLogLevelMapping[level])
+
self.assertEquals(log.eventDict["junk"], message)
# FIXME: this checks the end of message because we do formatting in emit()
@@ -170,7 +179,7 @@
try:
raise RuntimeError("baloney!")
except RuntimeError:
- log.failure()
+ log.failure("Whoops")
#
# log.failure() will cause trial to complain, so here we check that
@@ -181,6 +190,7 @@
self.assertEquals(len(errors), 1)
self.assertEquals(log.emitted["level"], LogLevel.error)
+ self.assertEquals(log.emitted["format"], "Whoops")
def test_conflicting_kwargs(self):
@@ -189,11 +199,25 @@
"""
log = TestLogger()
- log.error("*", logLevel="*", namespace="boogers")
- self.assertEquals(log.eventDict["logLevel"], logging.ERROR)
- self.assertEquals(log.eventDict["namespace"], log.namespace)
+ log.warn(
+ "*",
+ log_format = "#",
+ log_level = LogLevel.error,
+ log_levelName = "*level name*",
+ log_namespace = "*namespace*",
+ log_source = "*source*",
+ )
+ # FIXME: Should conflicts log errors?
+ self.assertNotEquals(log.eventDict["log_format"], "*")
+ self.assertNotEquals(log.eventDict["log_format"], "#")
+ self.assertEquals(log.eventDict["log_level"], LogLevel.warn)
+ self.assertEquals(log.eventDict["log_levelName"], LogLevel.warn.name)
+ self.assertEquals(log.eventDict["log_namespace"], log.namespace)
+ self.assertEquals(log.eventDict["log_source"], None)
+
+
def test_defaultLogLevel(self):
"""
Default log level is used.
@@ -330,7 +354,7 @@
log.msg(message, **kwargs)
self.assertIdentical(log.emitted["level"], LogLevel.info)
- self.assertEquals(log.emitted["message"], message)
+ self.assertEquals(log.emitted["format"], message)
for key, value in kwargs.items():
self.assertIdentical(log.emitted["kwargs"][key], value)
@@ -338,7 +362,7 @@
log.msg(foo="")
self.assertIdentical(log.emitted["level"], LogLevel.info)
- self.assertIdentical(log.emitted["message"], None)
+ self.assertIdentical(log.emitted["format"], None)
def test_legacy_err_implicit(self):
@@ -414,7 +438,7 @@
self.assertEquals(len(errors), 0)
self.assertIdentical(log.emitted["level"], LogLevel.error)
- self.assertEquals(log.emitted["message"], repr(bogus))
+ self.assertEquals(log.emitted["format"], repr(bogus))
self.assertIdentical(log.emitted["kwargs"]["why"], why)
for key, value in kwargs.items():
@@ -431,7 +455,7 @@
self.assertEquals(len(errors), 1)
self.assertIdentical(log.emitted["level"], LogLevel.error)
- self.assertEquals(log.emitted["message"], None)
+ 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)
Modified: CalendarServer/trunk/twext/web2/http.py
===================================================================
--- CalendarServer/trunk/twext/web2/http.py 2013-06-12 20:36:24 UTC (rev 11334)
+++ CalendarServer/trunk/twext/web2/http.py 2013-06-12 20:56:26 UTC (rev 11335)
@@ -489,9 +489,9 @@
def _error(self, reason):
if reason.check(error.ConnectionLost):
- log.info("Request error: " + reason.getErrorMessage())
+ log.info("Request error: {message}", message=reason.getErrorMessage())
else:
- log.failure(reason)
+ log.failure("Request error", reason)
# Only bother with cleanup on errors other than lost connection.
self.chanRequest.abortConnection()
Modified: CalendarServer/trunk/twext/web2/server.py
===================================================================
--- CalendarServer/trunk/twext/web2/server.py 2013-06-12 20:36:24 UTC (rev 11334)
+++ CalendarServer/trunk/twext/web2/server.py 2013-06-12 20:56:26 UTC (rev 11335)
@@ -629,10 +629,8 @@
return d
def _processingReallyFailed(self, reason, origReason):
- log.info("Exception rendering error page:", isErr=1)
- log.failure(reason)
- log.info("Original exception:", isErr=1)
- log.failure(origReason)
+ log.failure("Exception rendering error page", reason)
+ log.failure("Original exception", origReason)
body = ("<html><head><title>Internal Server Error</title></head>"
"<body><h1>Internal Server Error</h1>An error occurred rendering the requested page. Additionally, an error occurred rendering the error page.</body></html>")
@@ -670,8 +668,7 @@
raise TypeError("html is not a resource or a response")
def renderHTTP_exception(self, req, reason):
- log.info("Exception rendering:", isErr=1)
- log.failure(reason)
+ log.failure("Exception rendering request: {request}", reason, request=req)
body = ("<html><head><title>Internal Server Error</title></head>"
"<body><h1>Internal Server Error</h1>An error occurred rendering the requested page. More information is available in the server log.</body></html>")
Modified: CalendarServer/trunk/twext/web2/stream.py
===================================================================
--- CalendarServer/trunk/twext/web2/stream.py 2013-06-12 20:36:24 UTC (rev 11334)
+++ CalendarServer/trunk/twext/web2/stream.py 2013-06-12 20:56:26 UTC (rev 11335)
@@ -837,8 +837,7 @@
self._inputError)
def _inputError(self, f):
- log.info("Error in input stream for %r" % self.transport)
- log.failure(f)
+ log.failure("Error in input stream for transport {transport}", f, transport=self.transport)
self.transport.closeStdin()
def outReceived(self, data):
Modified: CalendarServer/trunk/twistedcaldav/directory/calendaruserproxyloader.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/calendaruserproxyloader.py 2013-06-12 20:36:24 UTC (rev 11334)
+++ CalendarServer/trunk/twistedcaldav/directory/calendaruserproxyloader.py 2013-06-12 20:56:26 UTC (rev 11335)
@@ -59,8 +59,8 @@
# Read in XML
try:
_ignore_tree, proxies_node = readXML(self.xmlFile, ELEMENT_PROXIES)
- except ValueError, e:
- log.failure("XML parse error for '%s'" % (self.xmlFile,), e)
+ except ValueError:
+ log.failure("XML parse error for proxy data file {xmlfile}", xmlfile=self.xmlFile)
# FIXME: RuntimeError is dumb.
self._parseXML(proxies_node)
Modified: CalendarServer/trunk/twistedcaldav/storebridge.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/storebridge.py 2013-06-12 20:36:24 UTC (rev 11334)
+++ CalendarServer/trunk/twistedcaldav/storebridge.py 2013-06-12 20:56:26 UTC (rev 11335)
@@ -480,7 +480,7 @@
try:
yield child.storeRemove(request)
except:
- log.failure()
+ log.failure("storeRemove({request})", request=request)
errors.add(childurl, BAD_REQUEST)
# Now do normal delete
@@ -2312,8 +2312,6 @@
# Grab the current exception state here so we can use it in a re-raise - we need this because
# an inlineCallback might be called and that raises an exception when it returns, wiping out the
# original exception "context".
- ex = Failure()
-
if type(err) in self.StoreMoveExceptionsStatusErrors:
raise HTTPError(StatusResponse(responsecode.FORBIDDEN, str(err)))
@@ -2325,7 +2323,7 @@
))
else:
# Return the original failure (exception) state
- ex.raiseException()
+ raise
def http_PROPPATCH(self, request):
Modified: CalendarServer/trunk/txdav/base/datastore/subpostgres.py
===================================================================
--- CalendarServer/trunk/txdav/base/datastore/subpostgres.py 2013-06-12 20:36:24 UTC (rev 11334)
+++ CalendarServer/trunk/txdav/base/datastore/subpostgres.py 2013-06-12 20:56:26 UTC (rev 11335)
@@ -457,7 +457,7 @@
self.ready(*createConnection())
self.deactivateDelayedShutdown()
def reportit(f):
- log.failure(f)
+ log.failure("starting postgres", f)
self.deactivateDelayedShutdown()
self.reactor.stop()
self.monitor.completionDeferred.addCallback(
Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/processing.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/scheduling/processing.py 2013-06-12 20:36:24 UTC (rev 11334)
+++ CalendarServer/trunk/txdav/caldav/datastore/scheduling/processing.py 2013-06-12 20:56:26 UTC (rev 11335)
@@ -115,7 +115,7 @@
# We attempt to recover from this. That involves trying to re-write the attendee data
# to match that of the organizer assuming we have the organizer's full data available, then
# we try the processing operation again.
- log.failure()
+ log.failure("{processor}.doImplicitAttendee()", processor=self)
log.error("ImplicitProcessing - originator '%s' to recipient '%s' with UID: '%s' - exception raised will try to fix: %s" % (self.originator.cuaddr, self.recipient.cuaddr, self.uid, e))
result = (yield self.doImplicitAttendeeEventFix(e))
if result:
@@ -123,7 +123,7 @@
try:
result = (yield self.doImplicitAttendee())
except Exception, e:
- log.failure()
+ log.failure("{processor}.doImplicitAttendee()", processor=self)
log.error("ImplicitProcessing - originator '%s' to recipient '%s' with UID: '%s' - exception raised after fix: %s" % (self.originator.cuaddr, self.recipient.cuaddr, self.uid, e))
raise ImplicitProcessorException("5.1;Service unavailable")
else:
Modified: CalendarServer/trunk/txdav/caldav/datastore/util.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/util.py 2013-06-12 20:36:24 UTC (rev 11334)
+++ CalendarServer/trunk/txdav/caldav/datastore/util.py 2013-06-12 20:56:26 UTC (rev 11335)
@@ -669,8 +669,7 @@
yield calObj.setComponent(comp)
except:
log.failure(
- format="Error while processing calendar/object %(calendarName)r %(calendarObject)r",
- failure=Failure(),
+ "Error while processing calendar/object {calendarName} {calendarObject}",
calendarName=calendar.name(),
calendarObject=calObj.name(),
)
Modified: CalendarServer/trunk/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/sql.py 2013-06-12 20:36:24 UTC (rev 11334)
+++ CalendarServer/trunk/txdav/common/datastore/sql.py 2013-06-12 20:56:26 UTC (rev 11335)
@@ -5558,7 +5558,7 @@
yield _normalizeColumnUUIDs(t, schema.RESOURCE_PROPERTY.VIEWER_UID)
yield _normalizeColumnUUIDs(t, schema.APN_SUBSCRIPTIONS.SUBSCRIBER_GUID)
except:
- log.failure()
+ log.failure("Unable to normalize UUIDs")
yield t.abort()
# There's a lot of possible problems here which are very hard to test
# for individually; unexpected data that might cause constraint
Modified: CalendarServer/trunk/txdav/common/datastore/test/util.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/test/util.py 2013-06-12 20:36:24 UTC (rev 11334)
+++ CalendarServer/trunk/txdav/common/datastore/test/util.py 2013-06-12 20:56:26 UTC (rev 11335)
@@ -291,7 +291,7 @@
try:
yield cleanupTxn.execSQL("delete from " + table, [])
except:
- log.failure()
+ log.failure("delete table {table} failed", table=table)
yield cleanupTxn.commit()
# Deal with memcached items that must be cleared
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20130612/7313bc9a/attachment-0001.html>
More information about the calendarserver-changes
mailing list