diff --git a/export_mailman2_settings.py b/export_mailman2_settings.py index 0bba152..6035dd5 100644 --- a/export_mailman2_settings.py +++ b/export_mailman2_settings.py @@ -1,26 +1,34 @@ import argparse import json import sys +from functools import partial +from copy import deepcopy from bs4 import BeautifulSoup -from mailman.interfaces.archiver import ArchivePolicy from mailman.interfaces.action import Action -from mailman.utilities.importer import NAME_MAPPINGS, member_moderation_action_mapping, dmarc_action_mapping, member_roster_visibility_mapping +from mailman.interfaces.archiver import ArchivePolicy +from mailman.interfaces.digests import DigestFrequency +from mailman.utilities.importer import ( + NAME_MAPPINGS, + EXCLUDES as EXCLUDES_ORIGINAL, + TYPES as TYPES_ORIGINAL, + member_moderation_action_mapping, + dmarc_action_mapping, + member_roster_visibility_mapping +) +from mailman.interfaces.nntp import NewsgroupModeration +from mailman.interfaces.mailinglist import ( + DMARCMitigateAction, + Personalization, + ReplyToMunging, + SubscriptionPolicy, +) KEYFILTER = ('submit') -EXCLUDES = set(( - # EXCLUDES in `importer.py` - 'accept_these_nonmembers', - 'delivery_status', - 'digest_members', - 'discard_these_nonmembers', - 'hold_these_nonmembers', - 'members', - 'reject_these_nonmembers', - 'user_options', -) + tuple({ +EXCLUDES = set( + tuple(EXCLUDES_ORIGINAL) + tuple({ # from `convert_to_uri` in mailman's `importer.py` 'goodbye_msg': 'list:user:notice:goodbye', 'msg_header': 'list:member:regular:header', @@ -74,11 +82,33 @@ EXCLUDES = set(( 'bounce_matching_headers', 'topic_rebox_01', 'topic_desc_01', - 'topics_enabled', 'topic_box_01', + # None of the lists has topic filtering enabled + 'topics_enabled', 'topics_bodylines_limit', )) +TYPES = deepcopy(TYPES_ORIGINAL) + +TYPES_EXTRA = { + 'autorespond_requests': lambda x, y: x(y).name, + 'autorespond_owner': lambda x, y: x(y).name, + 'autorespond_postings': lambda x, y: x(y).name, + 'autoresponse_grace_period': lambda x, y: '{}d'.format(x(y).days), + 'bounce_info_stale_after': lambda x, y: '{}s'.format(x(y).seconds), + 'bounce_you_are_disabled_warnings_interval': lambda x, y: '{}s'.format(x(y).seconds), + 'forward_unrecognized_bounces_to': lambda x, y: x(y).name, + 'filter_action': lambda x, y: x(y).name, + 'digest_volume_frequency': lambda x, y: x(y).name, + 'reply_goes_to_list': lambda x, y: x(y).name, + 'newsgroup_moderation': lambda x, y: x(y).name, + 'subscription_policy': lambda x, y: x(y).name, + 'default_nonmember_action': lambda x, y: x(y).name, +} + +for key, func in TYPES_EXTRA.items(): + TYPES[key] = partial(func, TYPES_ORIGINAL[key]) + def msg(*args, **kwargs): print(*args, file=sys.stderr, **kwargs) @@ -126,6 +156,16 @@ def get_form_data(htmlfile): except KeyError: value = '' + converter = TYPES.get(name) + try: + if converter is not None: + value = converter(value) + except (TypeError, KeyError, ValueError): + from pdb import set_trace; set_trace() + + print('Type conversion error for key "{}": {}'.format( + name, value), file=sys.stderr) + data_clean[name] = value return data_clean @@ -199,12 +239,13 @@ if __name__ == "__main__": # archive_private key, treat the list as having private archives. if globalconfig.get('archive_private', True): globalconfig['archive_policy'] = ArchivePolicy.private.name - del globalconfig['archive_private'] else: globalconfig['archive_policy'] = ArchivePolicy.public.name del globalconfig['archive'] else: globalconfig['archive_policy'] = ArchivePolicy.never.name + if 'archive_private' in globalconfig.keys(): + del globalconfig['archive_private'] # Handle roster visibility. mapping = member_roster_visibility_mapping(