diff options
Diffstat (limited to 'src/mailman/config/config.py')
| -rw-r--r-- | src/mailman/config/config.py | 84 |
1 files changed, 55 insertions, 29 deletions
diff --git a/src/mailman/config/config.py b/src/mailman/config/config.py index 3b662553e..0293dacd4 100644 --- a/src/mailman/config/config.py +++ b/src/mailman/config/config.py @@ -22,15 +22,17 @@ from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ 'Configuration', + 'external_configuration', + 'load_external' ] import os import sys -from ConfigParser import SafeConfigParser +from ConfigParser import SafeConfigParser from lazr.config import ConfigSchema, as_boolean -from pkg_resources import resource_stream, resource_exists +from pkg_resources import resource_filename, resource_stream, resource_string from string import Template from zope.component import getUtility from zope.event import notify @@ -40,7 +42,7 @@ import mailman.templates from mailman import version from mailman.interfaces.configuration import ( - ConfigurationUpdatedEvent, IConfiguration) + ConfigurationUpdatedEvent, IConfiguration, MissingConfigurationFileError) from mailman.interfaces.languages import ILanguageManager from mailman.utilities.filesystem import makedirs from mailman.utilities.modules import call_name @@ -237,30 +239,54 @@ class Configuration: for section in self._config.getByCategory('language', []): yield section - def get_additional_config(self, name, keyname): - """Return an external ini-file as specified by the keyname.""" - add_config = SafeConfigParser() - if resource_exists('mailman.config', '%s.cfg' % name): - included_config_file = resource_stream('mailman.config', - '%s.cfg' % name) - add_config.readfp(included_config_file) - # Resolve the path value from the key name - path = self._config - for key in keyname.split("."): - path = getattr(path, key) - # Load the file - configured_path = os.path.expanduser(path) # TODO: allow URLs - if not configured_path.startswith("/"): - # Consider it relative to the mailman.cfg file - for overlay in self.overlays: - if os.sep in overlay.filename: - configured_path = os.path.join( - os.path.dirname(overlay.filename), - configured_path) - break - r = add_config.read([configured_path]) - return add_config - def archiver_config(self, name): - """A shortcut to self.get_additional_config() for achivers.""" - return self.get_additional_config(name, "archiver.%s.configure" % name) + +def load_external(path, encoding=None): + """Load the configuration file named by path. + + :param path: A string naming the location of the external configuration + file. This is either an absolute file system path or a special + ``python:`` path. When path begins with ``python:``, the rest of the + value must name a ``.cfg`` file located within Python's import path, + however the trailing ``.cfg`` suffix is implied (don't provide it + here). + :param encoding: The encoding to apply to the data read from path. If + None, then bytes will be returned. + :return: A unicode string or bytes, depending on ``encoding``. + """ + # Is the context coming from a file system or Python path? + if path.startswith('python:'): + resource_path = path[7:] + package, dot, resource = resource_path.rpartition('.') + config_string = resource_string(package, resource + '.cfg') + else: + with open(path, 'rb') as fp: + config_string = fp.read() + if encoding is None: + return config_string + return config_string.decode(encoding) + + +def external_configuration(path): + """Parse the configuration file named by path. + + :param path: A string naming the location of the external configuration + file. This is either an absolute file system path or a special + ``python:`` path. When path begins with ``python:``, the rest of the + value must name a ``.cfg`` file located within Python's import path, + however the trailing ``.cfg`` suffix is implied (don't provide it + here). + :return: A `ConfigParser` instance. + """ + # Is the context coming from a file system or Python path? + if path.startswith('python:'): + resource_path = path[7:] + package, dot, resource = resource_path.rpartition('.') + cfg_path = resource_filename(package, resource + '.cfg') + else: + cfg_path = path + parser = SafeConfigParser() + files = parser.read(cfg_path) + if files != [cfg_path]: + raise MissingConfigurationFileError(path) + return parser |
