diff options
| -rw-r--r-- | src/mailman/commands/cli_import.py | 8 | ||||
| -rw-r--r-- | src/mailman/utilities/importer.py | 34 | ||||
| -rw-r--r-- | src/mailman/utilities/tests/test_import.py | 39 |
3 files changed, 76 insertions, 5 deletions
diff --git a/src/mailman/commands/cli_import.py b/src/mailman/commands/cli_import.py index c8145429d..880457334 100644 --- a/src/mailman/commands/cli_import.py +++ b/src/mailman/commands/cli_import.py @@ -35,7 +35,7 @@ from mailman.core.i18n import _ from mailman.database.transaction import transactional from mailman.interfaces.command import ICLISubCommand from mailman.interfaces.listmanager import IListManager -from mailman.utilities.importer import import_config_pck +from mailman.utilities.importer import import_config_pck, Import21Error @@ -93,4 +93,8 @@ class Import21: print(_('Ignoring non-dictionary: {0!r}').format( config_dict), file=sys.stderr) continue - import_config_pck(mlist, config_dict) + try: + import_config_pck(mlist, config_dict) + except Import21Error, e: + print(e, file=sys.stderr) + sys.exit(1) diff --git a/src/mailman/utilities/importer.py b/src/mailman/utilities/importer.py index 9ada4c75e..dcdc0e4c3 100644 --- a/src/mailman/utilities/importer.py +++ b/src/mailman/utilities/importer.py @@ -22,6 +22,7 @@ from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ 'import_config_pck', + 'ImportError', ] @@ -31,6 +32,7 @@ import os from urllib2 import URLError from mailman.config import config +from mailman.core.errors import MailmanError from mailman.interfaces.action import FilterAction, Action from mailman.interfaces.autorespond import ResponseAction from mailman.interfaces.digests import DigestFrequency @@ -42,12 +44,17 @@ from mailman.interfaces.mailinglist import IAcceptableAliasSet from mailman.interfaces.bounce import UnrecognizedBounceDisposition from mailman.interfaces.usermanager import IUserManager from mailman.interfaces.member import DeliveryMode, DeliveryStatus, MemberRole +from mailman.interfaces.languages import ILanguageManager from mailman.handlers.decorate import decorate, decorate_template from mailman.utilities.i18n import search from zope.component import getUtility +class Import21Error(MailmanError): + pass + + def seconds_to_delta(value): return datetime.timedelta(seconds=value) @@ -107,6 +114,26 @@ def nonmember_action_mapping(value): def unicode_to_string(value): return str(value) if value is not None else None + +def check_language_code(code): + if code is None: + return None + code = unicode(code) + if code not in getUtility(ILanguageManager): + msg = """Missing language: {0} +You must add a section describing this language in your mailman.cfg file. +This section should look like this: +[language.{1}] +# The English name for the language. +description: CHANGE ME +# And the default character set for the language. +charset: utf-8 +# Whether the language is enabled or not. +enabled: yes +""".format(code, code[:2]) + raise Import21Error(msg) + return code + # Attributes in Mailman 2 which have a different type in Mailman 3. TYPES = dict( @@ -129,6 +156,7 @@ TYPES = dict( default_member_action=member_action_mapping, default_nonmember_action=nonmember_action_mapping, moderator_password=unicode_to_string, + preferred_language=check_language_code, ) @@ -180,7 +208,9 @@ def import_config_pck(mlist, config_dict): # Handle the simple case where the key is an attribute of the # IMailingList and the types are the same (modulo 8-bit/unicode # strings). - if hasattr(mlist, key): + # When attributes raise an exception, hasattr may think they don't + # exist (see python issue 9666). Add them here. + if hasattr(mlist, key) or key in ("preferred_language", ): if isinstance(value, str): for encoding in ("ascii", "utf-8"): try: @@ -346,7 +376,7 @@ def import_roster(mlist, config_dict, members, role): pass if email in config_dict.get("language", {}): member.preferences.preferred_language = \ - unicode(config_dict["language"][email]) + check_language_code(config_dict["language"][email]) # if the user already exists, display_name and password will be # overwritten if email in config_dict.get("usernames", {}): diff --git a/src/mailman/utilities/tests/test_import.py b/src/mailman/utilities/tests/test_import.py index 2e6a4c0be..2cd737f08 100644 --- a/src/mailman/utilities/tests/test_import.py +++ b/src/mailman/utilities/tests/test_import.py @@ -31,7 +31,7 @@ from datetime import timedelta, datetime from mailman.app.lifecycle import create_list, remove_list from mailman.testing.layers import ConfigLayer -from mailman.utilities.importer import import_config_pck +from mailman.utilities.importer import import_config_pck, Import21Error from mailman.interfaces.archiver import ArchivePolicy from mailman.interfaces.action import Action, FilterAction from mailman.interfaces.bounce import UnrecognizedBounceDisposition @@ -226,6 +226,32 @@ class TestBasicImport(unittest.TestCase): unicode(self._pckdict[b"info"], "ascii", "replace"), "We don't fall back to replacing non-ascii chars") + def test_preferred_language(self): + self._pckdict[b"preferred_language"] = b'ja' + english = getUtility(ILanguageManager).get('en') + japanese = getUtility(ILanguageManager).get('ja') + self.assertEqual(self._mlist.preferred_language, english) + self._import() + self.assertEqual(self._mlist.preferred_language, japanese) + + def test_preferred_language_unknown_previous(self): + # when the previous language is unknown, it should not fail + self._mlist._preferred_language = 'xx' # non-existant + self._import() + english = getUtility(ILanguageManager).get('en') + self.assertEqual(self._mlist.preferred_language, english) + + def test_new_language(self): + self._pckdict[b"preferred_language"] = b'xx_XX' + try: + self._import() + except Import21Error, e: + # check the message + self.assertTrue("xx_XX" in str(e)) + self.assertTrue("[language.xx]" in str(e)) + else: + self.fail("Import21Error was not raised") + class TestArchiveImport(unittest.TestCase): @@ -549,6 +575,17 @@ class TestRosterImport(unittest.TestCase): self.assertEqual(member.preferred_language.code, self._pckdict["language"][addr]) + def test_new_language(self): + self._pckdict[b"language"][b"anne@example.com"] = b'xx_XX' + try: + import_config_pck(self._mlist, self._pckdict) + except Import21Error, e: + # check the message + self.assertTrue("xx_XX" in str(e)) + self.assertTrue("[language.xx]" in str(e)) + else: + self.fail("Import21Error was not raised") + def test_username(self): import_config_pck(self._mlist, self._pckdict) for name in ("anne", "bob", "cindy", "dave"): |
