Commit 125189ea authored by Fred Drake's avatar Fred Drake

Change the factory machinery to be a little less ad hoc.

parent 59fe6f63
......@@ -16,7 +16,8 @@ import sys
from logging import Handler, StreamHandler
from logging.handlers import SysLogHandler
from logging.handlers import HTTPHandler, SMTPHandler, NTEventLogHandler
from logging.handlers import HTTPHandler, SMTPHandler
from logging.handlers import NTEventLogHandler as Win32EventLogHandler
class FileHandler(StreamHandler):
"""
......
......@@ -12,14 +12,14 @@
<key name="level" default="info" datatype=".logging_level"/>
</sectiontype>
<sectiontype name="logfile" datatype=".file_handler"
<sectiontype name="logfile" datatype=".FileHandlerFactory"
implements="loghandler" extends="base-log-handler">
<key name="path" required="yes"/>
<key name="format" default="------\n%(asctime)s %(message)s"
datatype=".log_format"/>
</sectiontype>
<sectiontype name="syslog" datatype=".syslog_handler"
<sectiontype name="syslog" datatype=".SyslogHandlerFactory"
implements="loghandler" extends="base-log-handler">
<key name="facility" default="user" datatype=".syslog_facility"/>
<key name="address" datatype="socket-address" default="localhost:514"/>
......@@ -27,14 +27,14 @@
datatype=".log_format"/>
</sectiontype>
<sectiontype name="win32-eventlog" datatype=".nteventlog_handler"
<sectiontype name="win32-eventlog" datatype=".Win32EventLogFactory"
implements="loghandler" extends="base-log-handler">
<key name="appname" default="Zope"/>
<key name="format" default="%(message)s"
datatype=".log_format"/>
</sectiontype>
<sectiontype name="http-logger" datatype=".http_handler"
<sectiontype name="http-logger" datatype=".HTTPHandlerFactory"
implements="loghandler" extends="base-log-handler">
<key name="url" default="http://localhost/" datatype=".http_handler_url"/>
<key name="method" default="GET" datatype=".get_or_post"/>
......@@ -42,7 +42,7 @@
datatype=".log_format"/>
</sectiontype>
<sectiontype name="email-notifier" datatype=".smtp_handler"
<sectiontype name="email-notifier" datatype=".SMTPHandlerFactory"
implements="loghandler" extends="base-log-handler">
<key name="from" required="yes" attribute="fromaddr"/>
<multikey name="to" required="yes" attribute="toaddrs"/>
......
##############################################################################
#
# Copyright (c) 2002, 2003 Zope Corporation and Contributors.
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
......@@ -75,24 +75,32 @@ def ctrl_char_insert(value):
value = value.replace(pattern, replacement)
return value
def file_handler(section):
path = section.path
def callback(inst,
format=section.format,
dateformat=section.dateformat,
level=section.level):
class HandlerFactory(Factory):
def __init__(self, section):
Factory.__init__(self)
self.section = section
def create_logger(self):
raise NotImplementedError("subclasses must override create_logger()")
def create(self):
import logging
inst.setFormatter(logging.Formatter(format, dateformat))
inst.setLevel(level)
# XXX should pick up sys.{stderr,stdout} when the factory is invoked
if path == "STDERR":
return Factory('zLOG.LogHandlers.StreamHandler', callback, sys.stderr)
elif path == "STDOUT":
return Factory('zLOG.LogHandlers.StreamHandler', callback, sys.stdout)
else:
return Factory('zLOG.LogHandlers.FileHandler', callback, path)
logger = self.create_logger()
logger.setFormatter(logging.Formatter(self.section.format,
self.section.dateformat))
logger.setLevel(self.section.level)
return logger
class FileHandlerFactory(HandlerFactory):
def create_logger(self):
from zLOG.LogHandlers import StreamHandler, FileHandler
path = self.section.path
if path == "STDERR":
return StreamHandler(sys.stderr)
if path == "STDOUT":
return StreamHandler(sys.stdout)
return FileHandler(path)
_syslog_facilities = {
"auth": 1,
......@@ -125,30 +133,16 @@ def syslog_facility(value):
raise ValueError("Syslog facility must be one of " + ", ".join(L))
return value
def syslog_handler(section):
def callback(inst,
format=section.format,
dateformat=section.dateformat,
level=section.level):
import logging
inst.setFormatter(logging.Formatter(format, dateformat))
inst.setLevel(level)
return Factory('zLOG.LogHandlers.SysLogHandler', callback,
section.address.address,
section.facility)
def nteventlog_handler(section):
def callback(inst,
format=section.format,
dateformat=section.dateformat,
level=section.level):
import logging
inst.setFormatter(logging.Formatter(format, dateformat))
inst.setLevel(level)
class SyslogHandlerFactory(HandlerFactory):
def create_logger(self):
from zLOG.LogHandlers import SysLogHandler
return SysLogHandler(self.section.address.address,
self.section.facility)
return Factory('zLOG.LogHandlers.NTEventLogHandler', callback,
section.appname)
class Win32EventLogFactory(HandlerFactory):
def create_logger(self):
from zLOG.LogHandlers import Win32EventLogHandler
return Win32EventLogHandler(self.section.appname)
def http_handler_url(value):
import urlparse
......@@ -178,45 +172,25 @@ def get_or_post(value):
+ repr(value))
return value
def http_handler(section):
def callback(inst,
format=section.format,
dateformat=section.dateformat,
level=section.level):
import logging
inst.setFormatter(logging.Formatter(format, dateformat))
inst.setLevel(level)
host, selector = section.url
return Factory('zLOG.LogHandlers.HTTPHandler',
callback, host, selector, section.method)
def smtp_handler(section):
def callback(inst,
format=section.format,
dateformat=section.dateformat,
level=section.level):
import logging
inst.setFormatter(logging.Formatter(format, dateformat))
inst.setLevel(level)
host, port = section.smtp_server
if not port:
mailhost = host
else:
mailhost = host, port
return Factory('zLOG.LogHandlers.SMTPHandler',
callback,
mailhost,
section.fromaddr,
section.toaddrs,
section.subject)
_marker = []
class EventLogFactory:
class HTTPHandlerFactory(HandlerFactory):
def create_logger(self):
from zLOG.LogHandlers import HTTPHandler
host, selector = self.section.url
return HTTPHandler(host, selector, self.section.method)
class SMTPHandlerFactory(HandlerFactory):
def create_logger(self):
from zLOG.LogHandlers import SMTPHandler
host, port = self.section.smtp_server
if not port:
mailhost = host
else:
mailhost = host, port
return SMTPHandler(mailhost, self.section.fromaddr,
self.section.toaddrs, self.section.subject)
class EventLogFactory(Factory):
"""
A wrapper used to create loggers while delaying actual logger
instance construction. We need to do this because we may
......@@ -226,24 +200,22 @@ class EventLogFactory:
logger object.
"""
def __init__(self, section):
Factory.__init__(self)
self.level = section.level
self.handler_factories = section.handlers
self.resolved = _marker
def __call__(self):
if self.resolved is _marker:
# set the logger up
import logging
logger = logging.getLogger("event")
logger.handlers = []
logger.propagate = 0
logger.setLevel(self.level)
if self.handler_factories:
for handler_factory in self.handler_factories:
handler = handler_factory()
logger.addHandler(handler)
else:
from zLOG.LogHandlers import NullHandler
logger.addHandler(NullHandler())
self.resolved = logger
return self.resolved
def create(self):
# set the logger up
import logging
logger = logging.getLogger("event")
logger.handlers = []
logger.propagate = 0
logger.setLevel(self.level)
if self.handler_factories:
for handler_factory in self.handler_factories:
handler = handler_factory()
logger.addHandler(handler)
else:
from zLOG.LogHandlers import NullHandler
logger.addHandler(NullHandler())
return logger
......@@ -14,45 +14,23 @@
_marker = []
def importer(name):
components = name.split('.')
start = components[0]
g = globals()
package = __import__(start, g, g)
modulenames = [start]
for component in components[1:]:
modulenames.append(component)
try:
package = getattr(package, component)
except AttributeError:
name = '.'.join(modulenames)
package = __import__(name, g, g, component)
return package
class Factory:
"""Generic wrapper for instance construction.
Calling the factory causes the instance to be created if it hasn't
already been created, and returns the object. Calling the factory
multiple times returns the same object.
The instance is created using the factory's create() method, which
must be overriden by subclasses.
"""
A generic wrapper for instance construction and function calling used
to delay construction/call until necessary. The class path is the dotted
name to the class or function, args are the positional args, kw are the
keyword args. If it is specified, 'callback' is a function which will be
called back after constructing an instance or calling a function. It must
take the instance (or the result of the function) as a single argument.
"""
def __init__(self, class_path, callback, *args, **kw):
self.class_path = class_path
self.callback = callback
self.args = args
self.kw = kw
def __init__(self):
self.instance = _marker
def __repr__(self):
return ('<Factory instance for class "%s" with positional args "%s" '
'and keword args "%s"' % (self.class_path, self.args, self.kw))
def __call__(self):
if self.instance is _marker:
constructor = importer(self.class_path)
self.instance = constructor(*self.args, **self.kw)
if self.callback is not None:
self.callback(self.instance)
self.instance = self.create()
return self.instance
def create(self):
raise NotImplementedError("subclasses need to override create()")
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment