diff options
| author | Barry Warsaw | 2008-02-27 01:26:18 -0500 |
|---|---|---|
| committer | Barry Warsaw | 2008-02-27 01:26:18 -0500 |
| commit | a1c73f6c305c7f74987d99855ba59d8fa823c253 (patch) | |
| tree | 65696889450862357c9e05c8e9a589f1bdc074ac /Mailman/bin/export.py | |
| parent | 3f31f8cce369529d177cfb5a7c66346ec1e12130 (diff) | |
| download | mailman-a1c73f6c305c7f74987d99855ba59d8fa823c253.tar.gz mailman-a1c73f6c305c7f74987d99855ba59d8fa823c253.tar.zst mailman-a1c73f6c305c7f74987d99855ba59d8fa823c253.zip | |
Bite the bullet: rename the Mailman package to mailman.
Diffstat (limited to 'Mailman/bin/export.py')
| -rw-r--r-- | Mailman/bin/export.py | 313 |
1 files changed, 0 insertions, 313 deletions
diff --git a/Mailman/bin/export.py b/Mailman/bin/export.py deleted file mode 100644 index dccedaa55..000000000 --- a/Mailman/bin/export.py +++ /dev/null @@ -1,313 +0,0 @@ -# Copyright (C) 2006-2008 by the Free Software Foundation, Inc. -# -# This program 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 2 -# of the License, or (at your option) any later version. -# -# This program 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 this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, -# USA. - -"""Export an XML representation of a mailing list.""" - -import os -import re -import sha -import sys -import base64 -import codecs -import datetime -import optparse - -from xml.sax.saxutils import escape - -from Mailman import Defaults -from Mailman import Errors -from Mailman import MemberAdaptor -from Mailman import Version -from Mailman.MailList import MailList -from Mailman.configuration import config -from Mailman.i18n import _ -from Mailman.initialize import initialize - -SPACE = ' ' - -TYPES = { - Defaults.Toggle : 'bool', - Defaults.Radio : 'radio', - Defaults.String : 'string', - Defaults.Text : 'text', - Defaults.Email : 'email', - Defaults.EmailList : 'email_list', - Defaults.Host : 'host', - Defaults.Number : 'number', - Defaults.FileUpload : 'upload', - Defaults.Select : 'select', - Defaults.Topics : 'topics', - Defaults.Checkbox : 'checkbox', - Defaults.EmailListEx : 'email_list_ex', - Defaults.HeaderFilter : 'header_filter', - } - - - -class Indenter: - def __init__(self, fp, indentwidth=4): - self._fp = fp - self._indent = 0 - self._width = indentwidth - - def indent(self): - self._indent += 1 - - def dedent(self): - self._indent -= 1 - assert self._indent >= 0 - - def write(self, s): - if s <> '\n': - self._fp.write(self._indent * self._width * ' ') - self._fp.write(s) - - - -class XMLDumper(object): - def __init__(self, fp): - self._fp = Indenter(fp) - self._tagbuffer = None - self._stack = [] - - def _makeattrs(self, tagattrs): - # The attribute values might contain angle brackets. They might also - # be None. - attrs = [] - for k, v in tagattrs.items(): - if v is None: - v = '' - else: - v = escape(str(v)) - attrs.append('%s="%s"' % (k, v)) - return SPACE.join(attrs) - - def _flush(self, more=True): - if not self._tagbuffer: - return - name, attributes = self._tagbuffer - self._tagbuffer = None - if attributes: - attrstr = ' ' + self._makeattrs(attributes) - else: - attrstr = '' - if more: - print >> self._fp, '<%s%s>' % (name, attrstr) - self._fp.indent() - self._stack.append(name) - else: - print >> self._fp, '<%s%s/>' % (name, attrstr) - - # Use this method when you know you have sub-elements. - def _push_element(self, _name, **_tagattrs): - self._flush() - self._tagbuffer = (_name, _tagattrs) - - def _pop_element(self, _name): - buffered = bool(self._tagbuffer) - self._flush(more=False) - if not buffered: - name = self._stack.pop() - assert name == _name, 'got: %s, expected: %s' % (_name, name) - self._fp.dedent() - print >> self._fp, '</%s>' % name - - # Use this method when you do not have sub-elements - def _element(self, _name, _value=None, **_attributes): - self._flush() - if _attributes: - attrs = ' ' + self._makeattrs(_attributes) - else: - attrs = '' - if _value is None: - print >> self._fp, '<%s%s/>' % (_name, attrs) - else: - # The value might contain angle brackets. - value = escape(unicode(_value)) - print >> self._fp, '<%s%s>%s</%s>' % (_name, attrs, value, _name) - - def _do_list_categories(self, mlist, k, subcat=None): - info = mlist.GetConfigInfo(k, subcat) - label, gui = mlist.GetConfigCategories()[k] - if info is None: - return - for data in info[1:]: - if not isinstance(data, tuple): - continue - varname = data[0] - # Variable could be volatile - if varname.startswith('_'): - continue - vtype = data[1] - # Munge the value based on its type - value = None - if hasattr(gui, 'getValue'): - value = gui.getValue(mlist, vtype, varname, data[2]) - if value is None: - value = getattr(mlist, varname) - widget_type = TYPES[vtype] - if isinstance(value, list): - self._push_element('option', name=varname, type=widget_type) - for v in value: - self._element('value', v) - self._pop_element('option') - else: - self._element('option', value, name=varname, type=widget_type) - - def _dump_list(self, mlist): - # Write list configuration values - self._push_element('list', name=mlist.fqdn_listname) - self._push_element('configuration') - self._element('option', - mlist.preferred_language, - name='preferred_language') - for k in config.ADMIN_CATEGORIES: - subcats = mlist.GetConfigSubCategories(k) - if subcats is None: - self._do_list_categories(mlist, k) - else: - for subcat in [t[0] for t in subcats]: - self._do_list_categories(mlist, k, subcat) - self._pop_element('configuration') - # Write membership - self._push_element('roster') - digesters = set(mlist.getDigestMemberKeys()) - for member in sorted(mlist.getMembers()): - attrs = dict(id=member) - cased = mlist.getMemberCPAddress(member) - if cased <> member: - attrs['original'] = cased - self._push_element('member', **attrs) - self._element('realname', mlist.getMemberName(member)) - self._element('password', mlist.getMemberPassword(member)) - self._element('language', mlist.getMemberLanguage(member)) - # Delivery status, combined with the type of delivery - attrs = {} - status = mlist.getDeliveryStatus(member) - if status == MemberAdaptor.ENABLED: - attrs['status'] = 'enabled' - else: - attrs['status'] = 'disabled' - attrs['reason'] = {MemberAdaptor.BYUSER : 'byuser', - MemberAdaptor.BYADMIN : 'byadmin', - MemberAdaptor.BYBOUNCE : 'bybounce', - }.get(mlist.getDeliveryStatus(member), - 'unknown') - if member in digesters: - if mlist.getMemberOption(member, Defaults.DisableMime): - attrs['delivery'] = 'plain' - else: - attrs['delivery'] = 'mime' - else: - attrs['delivery'] = 'regular' - changed = mlist.getDeliveryStatusChangeTime(member) - if changed: - when = datetime.datetime.fromtimestamp(changed) - attrs['changed'] = when.isoformat() - self._element('delivery', **attrs) - for option, flag in Defaults.OPTINFO.items(): - # Digest/Regular delivery flag must be handled separately - if option in ('digest', 'plain'): - continue - value = mlist.getMemberOption(member, flag) - self._element(option, value) - topics = mlist.getMemberTopics(member) - if not topics: - self._element('topics') - else: - self._push_element('topics') - for topic in topics: - self._element('topic', topic) - self._pop_element('topics') - self._pop_element('member') - self._pop_element('roster') - self._pop_element('list') - - def dump(self, listnames): - print >> self._fp, '<?xml version="1.0" encoding="UTF-8"?>' - self._push_element('mailman', **{ - 'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance', - 'xsi:noNamespaceSchemaLocation': 'ssi-1.0.xsd', - }) - for listname in sorted(listnames): - try: - mlist = MailList(listname, lock=False) - except Errors.MMUnknownListError: - print >> sys.stderr, _('No such list: $listname') - continue - self._dump_list(mlist) - self._pop_element('mailman') - - def close(self): - while self._stack: - self._pop_element() - - - -def parseargs(): - parser = optparse.OptionParser(version=Version.MAILMAN_VERSION, - usage=_("""\ -%prog [options] - -Export the configuration and members of a mailing list in XML format.""")) - parser.add_option('-o', '--outputfile', - metavar='FILENAME', default=None, type='string', - help=_("""\ -Output XML to FILENAME. If not given, or if FILENAME is '-', standard out is -used.""")) - parser.add_option('-l', '--listname', - default=[], action='append', type='string', - metavar='LISTNAME', dest='listnames', help=_("""\ -The list to include in the output. If not given, then all mailing lists are -included in the XML output. Multiple -l flags may be given.""")) - parser.add_option('-C', '--config', - help=_('Alternative configuration file to use')) - opts, args = parser.parse_args() - if args: - parser.print_help() - parser.error(_('Unexpected arguments')) - return parser, opts, args - - - -def main(): - parser, opts, args = parseargs() - initialize(opts.config) - - close = False - if opts.outputfile in (None, '-'): - writer = codecs.getwriter('utf-8') - fp = writer(sys.stdout) - else: - fp = codecs.open(opts.outputfile, 'w', 'utf-8') - close = True - - try: - dumper = XMLDumper(fp) - if opts.listnames: - listnames = [] - for listname in opts.listnames: - if '@' not in listname: - listname = '%s@%s' % (listname, config.DEFAULT_EMAIL_HOST) - listnames.append(listname) - else: - listnames = config.list_manager.names - dumper.dump(listnames) - dumper.close() - finally: - if close: - fp.close() |
