diff options
| author | Barry Warsaw | 2012-11-04 15:49:08 -0500 |
|---|---|---|
| committer | Barry Warsaw | 2012-11-04 15:49:08 -0500 |
| commit | 89f6e779db51478ea95b71f2ad3dc9d7f5f51e05 (patch) | |
| tree | e1054919eb00e3abf73b4387277c4c79aca52b64 | |
| parent | 23fca2302ea2a8c5bad0a7aa450ea210ace7cf27 (diff) | |
| download | mailman-89f6e779db51478ea95b71f2ad3dc9d7f5f51e05.tar.gz mailman-89f6e779db51478ea95b71f2ad3dc9d7f5f51e05.tar.zst mailman-89f6e779db51478ea95b71f2ad3dc9d7f5f51e05.zip | |
22 files changed, 193 insertions, 69 deletions
diff --git a/src/mailman/app/tests/test_bounces.py b/src/mailman/app/tests/test_bounces.py index 4be272c34..fae30724e 100644 --- a/src/mailman/app/tests/test_bounces.py +++ b/src/mailman/app/tests/test_bounces.py @@ -320,9 +320,8 @@ $address $optionsurl $owneraddr """, file=fp) - # Python 2.7 has assertMultiLineEqual. Let this work without bounds. + # Let assertMultiLineEqual work without bounds. self.maxDiff = None - self.eq = getattr(self, 'assertMultiLineEqual', self.assertEqual) def tearDown(self): config.pop('xx template dir') @@ -343,7 +342,7 @@ $owneraddr send_probe(self._member, self._msg) message = get_queue_messages('virgin')[0].msg notice = message.get_payload(0).get_payload() - self.eq(notice, """\ + self.assertMultiLineEqual(notice, """\ blah blah blah test@example.com anne@example.com http://example.com/anne@example.com test-owner@example.com""") diff --git a/src/mailman/app/tests/test_inject.py b/src/mailman/app/tests/test_inject.py index 4e08ff0a7..7a47ed74a 100644 --- a/src/mailman/app/tests/test_inject.py +++ b/src/mailman/app/tests/test_inject.py @@ -55,16 +55,15 @@ Date: Tue, 14 Jun 2011 21:12:00 -0400 Nothing. """) - # Python 2.7 has assertMultiLineEqual. Let this work without bounds. - self.maxDiff = None - self.eq = getattr(self, 'assertMultiLineEqual', self.assertEqual) + # Let assertMultiLineEqual work without bounds. def test_inject_message(self): # Test basic inject_message() call. inject_message(self.mlist, self.msg) items = get_queue_messages('in') self.assertEqual(len(items), 1) - self.eq(items[0].msg.as_string(), self.msg.as_string()) + self.assertMultiLineEqual(items[0].msg.as_string(), + self.msg.as_string()) self.assertEqual(items[0].msgdata['listname'], 'test@example.com') self.assertEqual(items[0].msgdata['original_size'], len(self.msg.as_string())) @@ -83,7 +82,8 @@ Nothing. self.assertEqual(len(items), 0) items = get_queue_messages('virgin') self.assertEqual(len(items), 1) - self.eq(items[0].msg.as_string(), self.msg.as_string()) + self.assertMultiLineEqual(items[0].msg.as_string(), + self.msg.as_string()) self.assertEqual(items[0].msgdata['listname'], 'test@example.com') self.assertEqual(items[0].msgdata['original_size'], len(self.msg.as_string())) @@ -155,7 +155,6 @@ Nothing. """ # Python 2.7 has a better equality tester for message texts. self.maxDiff = None - self.eq = getattr(self, 'assertMultiLineEqual', self.assertEqual) def _remove_line(self, header): return NL.join(line for line in self.text.splitlines() @@ -171,7 +170,7 @@ Nothing. 'GUXXQKNCHBFQAHGBFMGCME6HKZCUUH3K') # Delete that header because it is not in the original text. del items[0].msg['x-message-id-hash'] - self.eq(items[0].msg.as_string(), self.text) + self.assertMultiLineEqual(items[0].msg.as_string(), self.text) self.assertEqual(items[0].msgdata['listname'], 'test@example.com') self.assertEqual(items[0].msgdata['original_size'], # Add back the X-Message-ID-Header which was in the @@ -196,7 +195,7 @@ Nothing. self.assertEqual(len(items), 1) # Remove the X-Message-ID-Hash header which isn't in the original text. del items[0].msg['x-message-id-hash'] - self.eq(items[0].msg.as_string(), self.text) + self.assertMultiLineEqual(items[0].msg.as_string(), self.text) self.assertEqual(items[0].msgdata['listname'], 'test@example.com') self.assertEqual(items[0].msgdata['original_size'], # Add back the X-Message-ID-Header which was in the diff --git a/src/mailman/app/tests/test_moderation.py b/src/mailman/app/tests/test_moderation.py index ef6adf5ed..dc1217d67 100644 --- a/src/mailman/app/tests/test_moderation.py +++ b/src/mailman/app/tests/test_moderation.py @@ -58,9 +58,6 @@ Message-ID: <alpha> self._in = make_testable_runner(IncomingRunner, 'in') self._pipeline = make_testable_runner(PipelineRunner, 'pipeline') self._out = make_testable_runner(OutgoingRunner, 'out') - # Python 2.7 has assertMultiLineEqual. Let this work without bounds. - self.maxDiff = None - self.eq = getattr(self, 'assertMultiLineEqual', self.assertEqual) def test_accepted_message_gets_posted(self): # A message that is accepted by the moderator should get posted to the diff --git a/src/mailman/app/tests/test_notifications.py b/src/mailman/app/tests/test_notifications.py index 8cce1be6f..303fa020a 100644 --- a/src/mailman/app/tests/test_notifications.py +++ b/src/mailman/app/tests/test_notifications.py @@ -74,9 +74,8 @@ Welcome to the $list_name mailing list. os.makedirs(path) with open(os.path.join(path, 'welcome.txt'), 'w') as fp: print('You just joined the $list_name mailing list!', file=fp) - # Python 2.7 has assertMultiLineEqual. Let this work without bounds. + # Let assertMultiLineEqual work without bounds. self.maxDiff = None - self.eq = getattr(self, 'assertMultiLineEqual', self.assertEqual) def tearDown(self): config.pop('template config') @@ -94,7 +93,7 @@ Welcome to the $list_name mailing list. message = messages[0].msg self.assertEqual(str(message['subject']), 'Welcome to the "Test List" mailing list') - self.eq(message.get_payload(), """\ + self.assertMultiLineEqual(message.get_payload(), """\ Welcome to the Test List mailing list. Posting address: test@example.com diff --git a/src/mailman/chains/tests/test_hold.py b/src/mailman/chains/tests/test_hold.py index 515894505..66f43fa60 100644 --- a/src/mailman/chains/tests/test_hold.py +++ b/src/mailman/chains/tests/test_hold.py @@ -44,9 +44,8 @@ class TestAutorespond(unittest.TestCase): def setUp(self): self._mlist = create_list('test@example.com') - # Python 2.7 has assertMultiLineEqual. Let this work without bounds. + # Let assertMultiLineEqual work without bounds. self.maxDiff = None - self.eq = getattr(self, 'assertMultiLineEqual', self.assertEqual) @configuration('mta', max_autoresponses_per_day=1) def test_max_autoresponses_per_day(self): @@ -71,7 +70,7 @@ class TestAutorespond(unittest.TestCase): del message['message-id'] self.assertTrue('date' in message) del message['date'] - self.eq(messages[0].msg.as_string(), """\ + self.assertMultiLineEqual(messages[0].msg.as_string(), """\ MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit diff --git a/src/mailman/commands/docs/aliases.rst b/src/mailman/commands/docs/aliases.rst index 89843c8ad..713064b0f 100644 --- a/src/mailman/commands/docs/aliases.rst +++ b/src/mailman/commands/docs/aliases.rst @@ -26,7 +26,6 @@ generation. ... incoming: mailman.mta.postfix.LMTP ... lmtp_host: lmtp.example.com ... lmtp_port: 24 - ... postfix_map_cmd: true ... """) Let's create a mailing list and then display the transport map for it. We'll diff --git a/src/mailman/config/config.py b/src/mailman/config/config.py index f6c39fcec..0293dacd4 100644 --- a/src/mailman/config/config.py +++ b/src/mailman/config/config.py @@ -22,14 +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 lazr.config import ConfigSchema, as_boolean -from pkg_resources import resource_stream +from pkg_resources import resource_filename, resource_stream, resource_string from string import Template from zope.component import getUtility from zope.event import notify @@ -39,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 @@ -235,3 +238,55 @@ class Configuration: """Iterate over all the language configuration sections.""" for section in self._config.getByCategory('language', []): yield section + + + +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 diff --git a/src/mailman/config/postfix.cfg b/src/mailman/config/postfix.cfg new file mode 100644 index 000000000..9bdba221e --- /dev/null +++ b/src/mailman/config/postfix.cfg @@ -0,0 +1,8 @@ +[postfix] +# Additional configuration variables for the postfix MTA. + +# This variable describe the program to use for regenerating the transport map +# db file, from the associated plain text files. The file being updated will +# be appended to this string (with a separating space), so it must be +# appropriate for os.system(). +postmap_command: /usr/sbin/postmap diff --git a/src/mailman/config/schema.cfg b/src/mailman/config/schema.cfg index e36d33c10..4e454fc86 100644 --- a/src/mailman/config/schema.cfg +++ b/src/mailman/config/schema.cfg @@ -159,7 +159,7 @@ wait: 10s # system paths must be absolute since no guarantees are made about the current # working directory. Python paths should not include the trailing .cfg, which # the file must end with. -path: python:mailman.config.passlib +configuration: python:mailman.config.passlib # When Mailman generates them, this is the default length of passwords. password_length: 8 @@ -513,11 +513,13 @@ max_autoresponses_per_day: 10 # may wish to remove these headers by setting this to 'yes'. remove_dkim_headers: no -# This variable describe the program to use for regenerating the transport map -# db file, from the associated plain text files. The file being updated will -# be appended to this string (with a separating space), so it must be -# appropriate for os.system(). -postfix_map_cmd: /usr/sbin/postmap +# Where can we find the mail server specific configuration file? The path can +# be either a file system path or a Python import path. If the value starts +# with python: then it is a Python import path, otherwise it is a file system +# path. File system paths must be absolute since no guarantees are made about +# the current working directory. Python paths should not include the trailing +# .cfg, which the file must end with. +configuration: python:mailman.config.postfix [bounces] diff --git a/src/mailman/config/tests/test_configuration.py b/src/mailman/config/tests/test_configuration.py index 88e00cbb9..08f27c094 100644 --- a/src/mailman/config/tests/test_configuration.py +++ b/src/mailman/config/tests/test_configuration.py @@ -22,12 +22,17 @@ from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ 'TestConfiguration', + 'TestExternal', ] import unittest -from mailman.interfaces.configuration import ConfigurationUpdatedEvent +from pkg_resources import resource_filename + +from mailman.config.config import external_configuration, load_external +from mailman.interfaces.configuration import ( + ConfigurationUpdatedEvent, MissingConfigurationFileError) from mailman.testing.helpers import configuration, event_subscribers from mailman.testing.layers import ConfigLayer @@ -51,3 +56,46 @@ class TestConfiguration(unittest.TestCase): # for the push leaving 'my test' on the top of the stack, and one for # the pop, leaving the ConfigLayer's 'test config' on top. self.assertEqual(events, ['my test', 'test config']) + + + +class TestExternal(unittest.TestCase): + """Test external configuration file loading APIs.""" + + def test_load_external_by_filename_as_bytes(self): + filename = resource_filename('mailman.config', 'postfix.cfg') + contents = load_external(filename) + self.assertIsInstance(contents, bytes) + self.assertEqual(contents[:9], b'[postfix]') + + def test_load_external_by_path_as_bytes(self): + contents = load_external('python:mailman.config.postfix') + self.assertIsInstance(contents, bytes) + self.assertEqual(contents[:9], b'[postfix]') + + def test_load_external_by_filename_as_string(self): + filename = resource_filename('mailman.config', 'postfix.cfg') + contents = load_external(filename, encoding='utf-8') + self.assertIsInstance(contents, unicode) + self.assertEqual(contents[:9], '[postfix]') + + def test_load_external_by_path_as_string(self): + contents = load_external('python:mailman.config.postfix', 'utf-8') + self.assertIsInstance(contents, unicode) + self.assertEqual(contents[:9], '[postfix]') + + def test_external_configuration_by_filename(self): + filename = resource_filename('mailman.config', 'postfix.cfg') + parser = external_configuration(filename) + self.assertEqual(parser.get('postfix', 'postmap_command'), + '/usr/sbin/postmap') + + def test_external_configuration_by_path(self): + parser = external_configuration('python:mailman.config.postfix') + self.assertEqual(parser.get('postfix', 'postmap_command'), + '/usr/sbin/postmap') + + def test_missing_configuration_file(self): + with self.assertRaises(MissingConfigurationFileError) as cm: + external_configuration('path:mailman.config.missing') + self.assertEqual(cm.exception.path, 'path:mailman.config.missing') diff --git a/src/mailman/docs/NEWS.rst b/src/mailman/docs/NEWS.rst index fb02f994d..3c7580126 100644 --- a/src/mailman/docs/NEWS.rst +++ b/src/mailman/docs/NEWS.rst @@ -35,6 +35,14 @@ REST unverify an address more than once, but verifying an already verified address does not change its `.verified_on` date. (LP: #1054730) +Configuration +------------- + * `[passlib]path` configuration variable renamed to `[passlib]configuration`. + * Postfix-specific configurations in the `[mta]` section are moved to a + separate file, named by the `[mta]configuration` variable. + * In the new `postfix.cfg` file, `postfix_map_cmd` is renamed to + `postmap_command`. + Database -------- * The `ban` table now uses list-ids to cross-reference the mailing list, diff --git a/src/mailman/handlers/tests/test_mimedel.py b/src/mailman/handlers/tests/test_mimedel.py index 74790fbf7..1f74db6ef 100644 --- a/src/mailman/handlers/tests/test_mimedel.py +++ b/src/mailman/handlers/tests/test_mimedel.py @@ -57,13 +57,12 @@ Subject: A disposable message Message-ID: <ant> """) - # Python 2.7 has assertMultiLineEqual. Let this work without bounds. - self.maxDiff = None - self.eq = getattr(self, 'assertMultiLineEqual', self.assertEqual) config.push('dispose', """ [mailman] site_owner: noreply@example.com """) + # Let assertMultiLineEqual work without bounds. + self.maxDiff = None def tearDown(self): config.pop('dispose') @@ -115,7 +114,7 @@ Message-ID: <ant> # The body of the first part provides the moderators some details. part0 = message.get_payload(0) self.assertEqual(part0.get_content_type(), 'text/plain') - self.eq(part0.get_payload(), """\ + self.assertMultiLineEqual(part0.get_payload(), """\ The attached message matched the Test mailing list's content filtering rules and was prevented from being forwarded on to the list membership. You are receiving the only remaining copy of the discarded diff --git a/src/mailman/interfaces/configuration.py b/src/mailman/interfaces/configuration.py index 8c4fb52a6..901706f91 100644 --- a/src/mailman/interfaces/configuration.py +++ b/src/mailman/interfaces/configuration.py @@ -23,11 +23,22 @@ __metaclass__ = type __all__ = [ 'ConfigurationUpdatedEvent', 'IConfiguration', + 'MissingConfigurationFileError', ] from zope.interface import Interface +from mailman.core.errors import MailmanError + + + +class MissingConfigurationFileError(MailmanError): + """A named configuration file was not found.""" + + def __init__(self, path): + self.path = path + class IConfiguration(Interface): diff --git a/src/mailman/mta/postfix.py b/src/mailman/mta/postfix.py index 072581374..ecd71db32 100644 --- a/src/mailman/mta/postfix.py +++ b/src/mailman/mta/postfix.py @@ -34,6 +34,7 @@ from zope.component import getUtility from zope.interface import implementer from mailman.config import config +from mailman.config.config import external_configuration from mailman.interfaces.listmanager import IListManager from mailman.interfaces.mta import ( IMailTransportAgentAliases, IMailTransportAgentLifecycle) @@ -60,6 +61,11 @@ class _FakeList: class LMTP: """Connect Mailman to Postfix via LMTP.""" + def __init__(self): + # Locate and read the Postfix specific configuration file. + mta_config = external_configuration(config.mta.configuration) + self.postmap_command = mta_config.get('postfix', 'postmap_command') + def create(self, mlist): """See `IMailTransportAgentLifecycle`.""" # We can ignore the mlist argument because for LMTP delivery, we just @@ -91,7 +97,7 @@ class LMTP: # one files, still try the other one. errors = [] for path in (lmtp_path, domains_path): - command = config.mta.postfix_map_cmd + ' ' + path + command = self.postmap_command + ' ' + path status = (os.system(command) >> 8) & 0xff if status: msg = 'command failure: %s, %s, %s' @@ -124,7 +130,7 @@ class LMTP: """.format(now().replace(microsecond=0)), file=fp) for domain in sorted(by_domain): print("""\ -# Aliases which are visible only in the @{0} domain.""".format(domain), +# Aliases which are visible only in the @{0} domain.""".format(domain), file=fp) for mlist in sorted(by_domain[domain], key=sort_key): aliases = list(utility.aliases(mlist)) diff --git a/src/mailman/mta/tests/test_aliases.py b/src/mailman/mta/tests/test_aliases.py index cc6b677b3..e22385dcf 100644 --- a/src/mailman/mta/tests/test_aliases.py +++ b/src/mailman/mta/tests/test_aliases.py @@ -37,7 +37,6 @@ from mailman.app.lifecycle import create_list from mailman.interfaces.domain import IDomainManager from mailman.interfaces.mta import IMailTransportAgentAliases from mailman.mta.postfix import LMTP -from mailman.testing.helpers import configuration from mailman.testing.layers import ConfigLayer @@ -145,14 +144,12 @@ class TestPostfix(unittest.TestCase): self.utility = getUtility(IMailTransportAgentAliases) self.mlist = create_list('test@example.com') self.postfix = LMTP() - # Python 2.7 has assertMultiLineEqual. Let this work without bounds. + # Let assertMultiLineEqual work without bounds. self.maxDiff = None - self.eq = getattr(self, 'assertMultiLineEqual', self.assertEqual) def tearDown(self): shutil.rmtree(self.tempdir) - @configuration('mta', postfix_map_cmd='true') def test_aliases(self): # Test the format of the Postfix alias generator. self.postfix.regenerate(self.tempdir) @@ -163,13 +160,13 @@ class TestPostfix(unittest.TestCase): # ignore the file header. with open(os.path.join(self.tempdir, 'postfix_domains')) as fp: contents = _strip_header(fp.read()) - self.eq(contents, """\ + self.assertMultiLineEqual(contents, """\ example.com example.com """) # The lmtp file contains transport mappings to the lmtp server. with open(os.path.join(self.tempdir, 'postfix_lmtp')) as fp: contents = _strip_header(fp.read()) - self.eq(contents, """\ + self.assertMultiLineEqual(contents, """\ # Aliases which are visible only in the @example.com domain. test@example.com lmtp:[127.0.0.1]:9024 test-bounces@example.com lmtp:[127.0.0.1]:9024 @@ -182,7 +179,6 @@ test-subscribe@example.com lmtp:[127.0.0.1]:9024 test-unsubscribe@example.com lmtp:[127.0.0.1]:9024 """) - @configuration('mta', postfix_map_cmd='true') def test_two_lists(self): # Both lists need to show up in the aliases file. LP: #874929. # Create a second list. @@ -195,13 +191,13 @@ test-unsubscribe@example.com lmtp:[127.0.0.1]:9024 # entry in the relays file. with open(os.path.join(self.tempdir, 'postfix_domains')) as fp: contents = _strip_header(fp.read()) - self.eq(contents, """\ + self.assertMultiLineEqual(contents, """\ example.com example.com """) # The transport file contains entries for both lists. with open(os.path.join(self.tempdir, 'postfix_lmtp')) as fp: contents = _strip_header(fp.read()) - self.eq(contents, """\ + self.assertMultiLineEqual(contents, """\ # Aliases which are visible only in the @example.com domain. other@example.com lmtp:[127.0.0.1]:9024 other-bounces@example.com lmtp:[127.0.0.1]:9024 @@ -224,7 +220,6 @@ test-subscribe@example.com lmtp:[127.0.0.1]:9024 test-unsubscribe@example.com lmtp:[127.0.0.1]:9024 """) - @configuration('mta', postfix_map_cmd='true') def test_two_lists_two_domains(self): # Now we have two lists in two different domains. Both lists will # show up in the postfix_lmtp file, and both domains will show up in @@ -239,14 +234,14 @@ test-unsubscribe@example.com lmtp:[127.0.0.1]:9024 # entry in the relays file. with open(os.path.join(self.tempdir, 'postfix_domains')) as fp: contents = _strip_header(fp.read()) - self.eq(contents, """\ + self.assertMultiLineEqual(contents, """\ example.com example.com example.net example.net """) # The transport file contains entries for both lists. with open(os.path.join(self.tempdir, 'postfix_lmtp')) as fp: contents = _strip_header(fp.read()) - self.eq(contents, """\ + self.assertMultiLineEqual(contents, """\ # Aliases which are visible only in the @example.com domain. test@example.com lmtp:[127.0.0.1]:9024 test-bounces@example.com lmtp:[127.0.0.1]:9024 diff --git a/src/mailman/mta/tests/test_delivery.py b/src/mailman/mta/tests/test_delivery.py index fbac0d121..c56058832 100644 --- a/src/mailman/mta/tests/test_delivery.py +++ b/src/mailman/mta/tests/test_delivery.py @@ -95,9 +95,8 @@ options : $user_optionsurl template_dir: {0} """.format(self._template_dir)) self._mlist.footer_uri = 'mailman:///member-footer.txt' - # Python 2.7 has assertMultiLineEqual. Let this work without bounds. + # Let assertMultiLineEqual work without bounds. self.maxDiff = None - self.eq = getattr(self, 'assertMultiLineEqual', self.assertEqual) def tearDown(self): # Free references. @@ -124,7 +123,7 @@ options : $user_optionsurl self.assertEqual(len(refused), 0) self.assertEqual(len(_deliveries), 1) _mlist, _msg, _msgdata, _recipients = _deliveries[0] - self.eq(_msg.as_string(), """\ + self.assertMultiLineEqual(_msg.as_string(), """\ From: anne@example.org To: test@example.com Subject: test diff --git a/src/mailman/rules/tests/test_approved.py b/src/mailman/rules/tests/test_approved.py index a1b8f99ac..19fa2bb06 100644 --- a/src/mailman/rules/tests/test_approved.py +++ b/src/mailman/rules/tests/test_approved.py @@ -462,7 +462,7 @@ schemes = roundup_plaintext, plaintext default = plaintext deprecated = roundup_plaintext """, file=fp) - with configuration('passwords', path=config_file): + with configuration('passwords', configuration=config_file): self._msg['Approved'] = 'super secret' result = self._rule.check(self._mlist, self._msg, {}) self.assertTrue(result) @@ -485,7 +485,7 @@ schemes = roundup_plaintext, plaintext default = plaintext deprecated = roundup_plaintext """, file=fp) - with configuration('passwords', path=config_file): + with configuration('passwords', configuration=config_file): self._msg['Approved'] = 'not the password' result = self._rule.check(self._mlist, self._msg, {}) self.assertFalse(result) diff --git a/src/mailman/runners/tests/test_owner.py b/src/mailman/runners/tests/test_owner.py index 4ea5771be..3118ab9f4 100644 --- a/src/mailman/runners/tests/test_owner.py +++ b/src/mailman/runners/tests/test_owner.py @@ -74,9 +74,6 @@ class TestEmailToOwner(unittest.TestCase): self._inq = make_testable_runner(IncomingRunner, 'in') self._pipelineq = make_testable_runner(PipelineRunner, 'pipeline') self._outq = make_testable_runner(OutgoingRunner, 'out') - # Python 2.7 has assertMultiLineEqual. Let this work without bounds. - self.maxDiff = None - self.eq = getattr(self, 'assertMultiLineEqual', self.assertEqual) def test_owners_get_email(self): # XXX 2012-03-23 BAW: We can't use a layer here because we need both diff --git a/src/mailman/testing/layers.py b/src/mailman/testing/layers.py index 3a3e1f684..99450d143 100644 --- a/src/mailman/testing/layers.py +++ b/src/mailman/testing/layers.py @@ -114,14 +114,25 @@ class ConfigLayer(MockAndMonkeyLayer): # runners) we'll need a file that we can specify to the with the -C # option. Craft the full test configuration string here, push it, and # also write it out to a temp file for -C. + # + # Create a dummy postfix.cfg file so that the test suite doesn't try + # to run the actual postmap command, which may not exist anyway. + postfix_cfg = os.path.join(cls.var_dir, 'postfix.cfg') + with open(postfix_cfg, 'w') as fp: + print(dedent(""" + [postfix] + postmap_command: true + """), file=fp) test_config = dedent(""" [mailman] layout: testing [paths.testing] - var_dir: %s + var_dir: {0} [devmode] testing: yes - """ % cls.var_dir) + [mta] + configuration: {1} + """.format(cls.var_dir, postfix_cfg)) # Read the testing config and push it. test_config += resource_string('mailman.testing', 'testing.cfg') config.create_paths = True diff --git a/src/mailman/testing/testing.cfg b/src/mailman/testing/testing.cfg index 141d74a8f..7d57aa681 100644 --- a/src/mailman/testing/testing.cfg +++ b/src/mailman/testing/testing.cfg @@ -31,7 +31,7 @@ lmtp_port: 9024 incoming: mailman.testing.mta.FakeMTA [passwords] -path: python:mailman.testing.passlib +configuration: python:mailman.testing.passlib [webservice] port: 9001 diff --git a/src/mailman/utilities/passwords.py b/src/mailman/utilities/passwords.py index 95c85c47a..cf08260fa 100644 --- a/src/mailman/utilities/passwords.py +++ b/src/mailman/utilities/passwords.py @@ -27,22 +27,15 @@ __all__ = [ from passlib.context import CryptContext -from pkg_resources import resource_string +from mailman.config.config import load_external from mailman.interfaces.configuration import ConfigurationUpdatedEvent class PasswordContext: def __init__(self, config): - # Is the context coming from a file system or Python path? - if config.passwords.path.startswith('python:'): - resource_path = config.passwords.path[7:] - package, dot, resource = resource_path.rpartition('.') - config_string = resource_string(package, resource + '.cfg') - else: - with open(config.passwords.path, 'rb') as fp: - config_string = fp.read() + config_string = load_external(config.passwords.configuration) self._context = CryptContext.from_string(config_string) def encrypt(self, secret): diff --git a/src/mailman/utilities/tests/test_passwords.py b/src/mailman/utilities/tests/test_passwords.py index 7b2931855..22ef22757 100644 --- a/src/mailman/utilities/tests/test_passwords.py +++ b/src/mailman/utilities/tests/test_passwords.py @@ -55,6 +55,6 @@ class TestPasswords(unittest.TestCase): [passlib] schemes = plaintext """, file=fp) - with configuration('passwords', path=config_file): + with configuration('passwords', configuration=config_file): self.assertEqual(config.password_context.encrypt('my password'), 'my password') |
