diff options
| -rw-r--r-- | src/mailman/app/lifecycle.py | 9 | ||||
| -rw-r--r-- | src/mailman/bin/genaliases.py | 5 | ||||
| -rw-r--r-- | src/mailman/bin/master.py | 6 | ||||
| -rw-r--r-- | src/mailman/bin/qrunner.py | 9 | ||||
| -rw-r--r-- | src/mailman/config/config.py | 6 | ||||
| -rw-r--r-- | src/mailman/core/initialize.py | 13 | ||||
| -rw-r--r-- | src/mailman/database/pending.py | 8 | ||||
| -rw-r--r-- | src/mailman/database/types.py | 8 | ||||
| -rw-r--r-- | src/mailman/pipeline/scrubber.py | 11 | ||||
| -rw-r--r-- | src/mailman/queue/lmtp.py | 2 | ||||
| -rw-r--r-- | src/mailman/queue/outgoing.py | 6 | ||||
| -rw-r--r-- | src/mailman/styles/manager.py | 5 | ||||
| -rw-r--r-- | src/mailman/utilities/modules.py | 59 |
13 files changed, 95 insertions, 52 deletions
diff --git a/src/mailman/app/lifecycle.py b/src/mailman/app/lifecycle.py index 56eb88d32..051b7cec3 100644 --- a/src/mailman/app/lifecycle.py +++ b/src/mailman/app/lifecycle.py @@ -36,6 +36,7 @@ from mailman.config import config from mailman.core import errors from mailman.email.validate import validate from mailman.interfaces.member import MemberRole +from mailman.utilities.modules import call_name log = logging.getLogger('mailman.error') @@ -54,9 +55,7 @@ def create_list(fqdn_listname, owners=None): for style in config.style_manager.lookup(mlist): style.apply(mlist) # Coordinate with the MTA, as defined in the configuration file. - package, dot, class_name = config.mta.incoming.rpartition('.') - __import__(package) - getattr(sys.modules[package], class_name)().create(mlist) + call_name(config.mta.incoming).create(mlist) # Create any owners that don't yet exist, and subscribe all addresses as # owners of the mailing list. usermgr = config.db.user_manager @@ -83,9 +82,7 @@ def remove_list(fqdn_listname, mailing_list=None, archives=True): # Delete the mailing list from the database. config.db.list_manager.delete(mailing_list) # Do the MTA-specific list deletion tasks - package, dot, class_name = config.mta.incoming.rpartition('.') - __import__(package) - getattr(sys.modules[package], class_name)().create(mailing_list) + call_name(config.mta.incoming).create(mailing_list) # Remove the list directory. removeables.append(os.path.join(config.LIST_DATA_DIR, fqdn_listname)) # Remove any stale locks associated with the list. diff --git a/src/mailman/bin/genaliases.py b/src/mailman/bin/genaliases.py index fe587cb02..8fe37f543 100644 --- a/src/mailman/bin/genaliases.py +++ b/src/mailman/bin/genaliases.py @@ -26,6 +26,7 @@ import sys from mailman.config import config from mailman.i18n import _ from mailman.options import Options +from mailman.utilities.modules import call_name @@ -54,9 +55,7 @@ def main(): options.initialize() # Get the MTA-specific module. - package, dot, class_path = config.mta.incoming.rpartition('.') - __import__(module_path) - getattr(sys.modules[module_path], class_path)().regenerate() + call_name(config.mta.incoming).regenerate() diff --git a/src/mailman/bin/master.py b/src/mailman/bin/master.py index 1156f8a33..076b3acfb 100644 --- a/src/mailman/bin/master.py +++ b/src/mailman/bin/master.py @@ -40,6 +40,7 @@ from mailman.config import config from mailman.core.logging import reopen from mailman.i18n import _ from mailman.options import Options +from mailman.utilities.modules import find_name DOT = '.' @@ -319,10 +320,7 @@ class Loop: qrunner_config = getattr(config, section_name) if not as_boolean(qrunner_config.start): continue - package, dot, class_name = qrunner_config['class'].rpartition(DOT) - __import__(package) - # Let AttributeError propagate. - class_ = getattr(sys.modules[package], class_name) + class_ = find_name(qrunner_config['class']) # Find out how many qrunners to instantiate. This must be a power # of 2. count = int(qrunner_config.instances) diff --git a/src/mailman/bin/qrunner.py b/src/mailman/bin/qrunner.py index 99cb564bc..318b62c68 100644 --- a/src/mailman/bin/qrunner.py +++ b/src/mailman/bin/qrunner.py @@ -23,6 +23,7 @@ from mailman.config import config from mailman.core.logging import reopen from mailman.i18n import _ from mailman.options import Options +from mailman.utilities.modules import find_name COMMASPACE = ', ' @@ -133,19 +134,17 @@ def make_qrunner(name, slice, range, once=False): class_path = 'mailman.queue' + name else: class_path = name - package, dot, class_name = class_path.rpartition('.') try: - __import__(package) - except ImportError, e: + qrclass = find_name(class_path) + except ImportError as error: if config.options.options.subproc: # Exit with SIGTERM exit code so the master watcher won't try to # restart us. print >> sys.stderr, _('Cannot import runner module: $module_name') - print >> sys.stderr, e + print >> sys.stderr, error sys.exit(signal.SIGTERM) else: raise - qrclass = getattr(sys.modules[package], class_name) if once: # Subclass to hack in the setting of the stop flag in _do_periodic() class Once(qrclass): diff --git a/src/mailman/config/config.py b/src/mailman/config/config.py index 1b86e8f67..4ae2e85be 100644 --- a/src/mailman/config/config.py +++ b/src/mailman/config/config.py @@ -39,6 +39,8 @@ from mailman.domain import Domain from mailman.languages.manager import LanguageManager from mailman.styles.manager import StyleManager from mailman.utilities.filesystem import makedirs +from mailman.utilities.modules import call_name + SPACE = ' ' @@ -191,9 +193,7 @@ class Configuration(object): if not as_boolean(section.enable): continue class_path = section['class'] - package, dot, class_name = class_path.rpartition('.') - __import__(package) - yield getattr(sys.modules[package], class_name)() + yield call_name(class_path) @property def style_configs(self): diff --git a/src/mailman/core/initialize.py b/src/mailman/core/initialize.py index 18cb823ee..885174fb0 100644 --- a/src/mailman/core/initialize.py +++ b/src/mailman/core/initialize.py @@ -45,6 +45,7 @@ import mailman.config.config import mailman.core.logging from mailman.interfaces.database import IDatabase +from mailman.utilities.modules import call_name @@ -92,15 +93,11 @@ def initialize_2(debug=False): # Run the pre-hook if there is one. config = mailman.config.config if config.mailman.pre_hook: - package, dot, function = config.mailman.pre_hook.rpartition('.') - __import__(package) - getattr(sys.modules[package], function)() + call_name(config.mailman.pre_hook) # Instantiate the database class, ensure that it's of the right type, and # initialize it. Then stash the object on our configuration object. database_class = config.database['class'] - package, dot, class_name = database_class.rpartition('.') - __import__(package) - database = getattr(sys.modules[package], class_name)() + database = call_name(database_class) verifyObject(IDatabase, database) database.initialize(debug) config.db = database @@ -132,9 +129,7 @@ def initialize_3(): # Run the post-hook if there is one. config = mailman.config.config if config.mailman.post_hook: - package, dot, function = config.mailman.post_hook.rpartition('.') - __import__(package) - getattr(sys.modules[package], function)() + call_name(config.mailman.post_hook) diff --git a/src/mailman/database/pending.py b/src/mailman/database/pending.py index 9c2da9064..2a0e5d09e 100644 --- a/src/mailman/database/pending.py +++ b/src/mailman/database/pending.py @@ -40,6 +40,7 @@ from mailman.config import config from mailman.database.model import Model from mailman.interfaces.pending import ( IPendable, IPended, IPendedKeyValue, IPendings) +from mailman.utilities.modules import call_name @@ -145,11 +146,8 @@ class Pendings: for keyvalue in store.find(PendedKeyValue, PendedKeyValue.pended_id == pending.id): if keyvalue.value is not None and '\1' in keyvalue.value: - typename, value = keyvalue.value.split('\1', 1) - package, dot, classname = typename.rpartition('.') - __import__(package) - module = sys.modules[package] - pendable[keyvalue.key] = getattr(module, classname)(value) + type_name, value = keyvalue.value.split('\1', 1) + pendable[keyvalue.key] = call_name(type_name, value) else: pendable[keyvalue.key] = keyvalue.value if expunge: diff --git a/src/mailman/database/types.py b/src/mailman/database/types.py index 4b3031c3b..f559737e2 100644 --- a/src/mailman/database/types.py +++ b/src/mailman/database/types.py @@ -31,6 +31,8 @@ import sys from storm.properties import SimpleProperty from storm.variables import Variable +from mailman.utilities.modules import find_name + class _EnumVariable(Variable): @@ -42,10 +44,8 @@ class _EnumVariable(Variable): if not from_db: return value path, colon, intvalue = value.rpartition(':') - package, dot, classname = path.rpartition('.') - __import__(package) - cls = getattr(sys.modules[package], classname) - return cls[int(intvalue)] + class_ = find_name(path) + return class_[int(intvalue)] def parse_get(self, value, to_db): if value is None: diff --git a/src/mailman/pipeline/scrubber.py b/src/mailman/pipeline/scrubber.py index 18d50c7a5..e5510e0ab 100644 --- a/src/mailman/pipeline/scrubber.py +++ b/src/mailman/pipeline/scrubber.py @@ -49,6 +49,7 @@ from mailman.core.errors import DiscardMessage from mailman.i18n import _ from mailman.interfaces.handler import IHandler from mailman.utilities.filesystem import makedirs +from mailman.utilities.modules import find_name # Path characters for common platforms @@ -487,14 +488,12 @@ def save_attachment(mlist, msg, dir, filter_html=True): fp.close() # Now calculate the url to the list's archive. scrubber_path = config.scrubber.archive_scrubber - package, dot, module_name = scrubber_path.rpartition('.') - __import__(package) - baseurl = getattr(sys.modules[package], module_name).list_url(mlist) - if not baseurl.endswith('/'): - baseurl += '/' + base_url = find_name(scrubber_path).list_url(mlist) + if not base_url.endswith('/'): + base_url += '/' # Trailing space will definitely be a problem with format=flowed. # Bracket the URL instead. - url = '<' + baseurl + '%s/%s%s%s>' % (dir, filebase, extra, ext) + url = '<' + base_url + '%s/%s%s%s>' % (dir, filebase, extra, ext) return url diff --git a/src/mailman/queue/lmtp.py b/src/mailman/queue/lmtp.py index 68a86eeb3..00c9ad988 100644 --- a/src/mailman/queue/lmtp.py +++ b/src/mailman/queue/lmtp.py @@ -119,9 +119,9 @@ class LMTPRunner(Runner, smtpd.SMTPServer): def __init__(self, slice=None, numslices=1): localaddr = config.mta.lmtp_host, int(config.mta.lmtp_port) # Do not call Runner's constructor because there's no QDIR to create - smtpd.SMTPServer.__init__(self, localaddr, remoteaddr=None) qlog.debug('LMTP server listening on %s:%s', localaddr[0], localaddr[1]) + smtpd.SMTPServer.__init__(self, localaddr, remoteaddr=None) def handle_accept(self): conn, addr = self.accept() diff --git a/src/mailman/queue/outgoing.py b/src/mailman/queue/outgoing.py index 2093534b4..e64e8c57b 100644 --- a/src/mailman/queue/outgoing.py +++ b/src/mailman/queue/outgoing.py @@ -29,6 +29,8 @@ from mailman.config import config from mailman.core import errors from mailman.queue import Runner from mailman.queue.bounce import BounceMixin +from mailman.utilities.modules import find_name + # This controls how often _do_periodic() will try to deal with deferred # permanent failures. It is a count of calls to _do_periodic() @@ -45,9 +47,7 @@ class OutgoingRunner(Runner, BounceMixin): Runner.__init__(self, slice, numslices) BounceMixin.__init__(self) # We look this function up only at startup time. - package, dot, callable_name = config.mta.outgoing.rpartition('.') - __import__(package) - self._func = getattr(sys.modules[package], callable_name) + self._func = find_name(config.mta.outgoing) # This prevents smtp server connection problems from filling up the # error log. It gets reset if the message was successfully sent, and # set if there was a socket.error. diff --git a/src/mailman/styles/manager.py b/src/mailman/styles/manager.py index e9682d7c5..fb7c54efd 100644 --- a/src/mailman/styles/manager.py +++ b/src/mailman/styles/manager.py @@ -33,6 +33,7 @@ from zope.interface.verify import verifyObject from mailman.interfaces.styles import ( DuplicateStyleError, IStyle, IStyleManager) +from mailman.utilities.modules import call_name @@ -52,9 +53,7 @@ class StyleManager: # Install all the styles described by the configuration files. for section in config.style_configs: class_path = section['class'] - package, dot, class_name = class_path.rpartition('.') - __import__(package) - style = getattr(sys.modules[package], class_name)() + style = call_name(class_path) assert section.name.startswith('style'), ( 'Bad style section name: %s' % section.name) style.name = section.name[6:] diff --git a/src/mailman/utilities/modules.py b/src/mailman/utilities/modules.py new file mode 100644 index 000000000..bcee3f39e --- /dev/null +++ b/src/mailman/utilities/modules.py @@ -0,0 +1,59 @@ +# Copyright (C) 2009 by the Free Software Foundation, Inc. +# +# This file is part of GNU Mailman. +# +# GNU Mailman is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) +# any later version. +# +# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# GNU Mailman. If not, see <http://www.gnu.org/licenses/>. + +"""Package and module utilities.""" + +from __future__ import absolute_import, unicode_literals + +__metaclass__ = type +__all__ = [ + 'call_name' + 'find_name', + ] + + +import sys + + + +def find_name(dotted_name): + """Import and return the named object in package space. + + :param dotted_name: The dotted module path name to the object. + :type dotted_name: string + :return: The object. + :rtype: object + """ + package_path, dot, object_name = dotted_name.rpartition('.') + __import__(package_path) + return getattr(sys.modules[package_path], object_name) + + +def call_name(dotted_name, *args, **kws): + """Imports and calls the named object in package space. + + :param dotted_name: The dotted module path name to the object. + :type dotted_name: string + :param args: The positional arguments. + :type args: tuple + :param kws: The keyword arguments. + :type kws: dict + :return: The object. + :rtype: object + """ + named_callable = find_name(dotted_name) + return named_callable(*args, **kws) |
