diff options
| -rw-r--r-- | Mailman/Defaults.py.in | 2 | ||||
| -rwxr-xr-x | Mailman/bin/newlist.py | 9 | ||||
| -rwxr-xr-x | Mailman/bin/rmlist.py | 134 | ||||
| -rw-r--r-- | Mailman/i18n.py | 27 | ||||
| -rw-r--r-- | Mailman/loginit.py | 43 |
5 files changed, 108 insertions, 107 deletions
diff --git a/Mailman/Defaults.py.in b/Mailman/Defaults.py.in index 23aa50dec..9ed247b67 100644 --- a/Mailman/Defaults.py.in +++ b/Mailman/Defaults.py.in @@ -1302,6 +1302,8 @@ PIDFILE = os.path.join(DATA_DIR, 'master-qrunner.pid') SITE_PW_FILE = os.path.join(DATA_DIR, 'adm.pw') LISTCREATOR_PW_FILE = os.path.join(DATA_DIR, 'creator.pw') + + # Import a bunch of version numbers from Version import * diff --git a/Mailman/bin/newlist.py b/Mailman/bin/newlist.py index 79b584eee..2a103c15b 100755 --- a/Mailman/bin/newlist.py +++ b/Mailman/bin/newlist.py @@ -25,20 +25,21 @@ from Mailman import Errors from Mailman import MailList from Mailman import Message from Mailman import Utils -from Mailman import Version from Mailman import i18n from Mailman import mm_cfg _ = i18n._ +__i18n_templates__ = True + def parseargs(): - parser = optparse.OptionParser(version='GNU Mailman ' + Version.VERSION, + parser = optparse.OptionParser(version='GNU Mailman ' + mm_cfg.VERSION, usage=_("""\ -Create a new, unpopulated mailing list. +%%prog [options] [listname [listadmin-addr [admin-password]]] -Usage: %%prog [options] [listname [listadmin-addr [admin-password]]] +Create a new, unpopulated mailing list. You can specify as many of the arguments as you want on the command line: you will be prompted for the missing ones. diff --git a/Mailman/bin/rmlist.py b/Mailman/bin/rmlist.py index fbaf30641..e2d41c8d9 100755 --- a/Mailman/bin/rmlist.py +++ b/Mailman/bin/rmlist.py @@ -1,6 +1,4 @@ -#! @PYTHON@ -# -# Copyright (C) 1998-2003 by the Free Software Foundation, Inc. +# Copyright (C) 1998-2006 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 @@ -14,125 +12,99 @@ # # 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. - -"""Remove the components of a mailing list with impunity - beware! - -This removes (almost) all traces of a mailing list. By default, the lists -archives are not removed, which is very handy for retiring old lists. - -Usage: - rmlist [-a] [-h] listname - -Where: - --archives - -a - Remove the list's archives too, or if the list has already been - deleted, remove any residual archives. - - --help - -h - Print this help message and exit. - -""" +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. import os import sys -import getopt import shutil +import optparse -import paths -from Mailman import mm_cfg -from Mailman import Utils from Mailman import MailList +from Mailman import Utils +from Mailman import mm_cfg from Mailman.i18n import _ -try: - True, False -except NameError: - True = 1 - False = 0 - - - -def usage(code, msg=''): - if code: - fd = sys.stderr - else: - fd = sys.stdout - print >> fd, _(__doc__) - if msg: - print >> fd, msg - sys.exit(code) +__i18n_templates__ = True def remove_it(listname, filename, msg): if os.path.islink(filename): - print _('Removing %(msg)s') + print _('Removing $msg') os.unlink(filename) elif os.path.isdir(filename): - print _('Removing %(msg)s') + print _('Removing $msg') shutil.rmtree(filename) elif os.path.isfile(filename): os.unlink(filename) else: - print _('%(listname)s %(msg)s not found as %(filename)s') + print _('$listname $msg not found as $filename') -def main(): - try: - opts, args = getopt.getopt(sys.argv[1:], 'ah', - ['archives', 'help']) - except getopt.error, msg: - usage(1, msg) +def parseargs(): + parser = optparse.OptionParser(version='GNU Mailman ' + mm_cfg.VERSION, + usage=_("""\ +%%prog [options] listname - if len(args) <> 1: - usage(1) - listname = args[0].lower().strip() +Remove the components of a mailing list with impunity - beware! - removeArchives = False - for opt, arg in opts: - if opt in ('-a', '--archives'): - removeArchives = True - elif opt in ('-h', '--help'): - usage(0) +This removes (almost) all traces of a mailing list. By default, the lists +archives are not removed, which is very handy for retiring old lists. +""")) + parser.add_option('-a', '--archives', + default=False, action='store_true', help=_("""\ +Remove the list's archives too, or if the list has already been deleted, +remove any residual archives.""")) + opts, args = parser.parse_args() + if not args: + parser.print_help() + print >> sys.stderr, _('Missing listname') + sys.exit(1) + if len(args) > 1: + parser.print_help() + print >> sys.stderr, _('Unexpected arguments') + sys.exit(1) + return parser, opts, args + + +def main(): + parser, opts, args = parseargs() + listname = args[0].lower().strip() if not Utils.list_exists(listname): - if not removeArchives: - usage(1, _('No such list (or list already deleted): %(listname)s')) + if not opts.archives: + print >> sys.stderr, _( + 'No such list (or list already deleted): $listname') + sys.exit(1) else: print _( - 'No such list: %(listname)s. Removing its residual archives.') + 'No such list: $listname. Removing its residual archives.') - if not removeArchives: + if not opts.archives: print _('Not removing archives. Reinvoke with -a to remove them.') - - REMOVABLES = [] + removeables = [] if Utils.list_exists(listname): - mlist = MailList.MailList(listname, lock=0) - + mlist = MailList.MailList(listname, lock=False) # Do the MTA-specific list deletion tasks if mm_cfg.MTA: modname = 'Mailman.MTA.' + mm_cfg.MTA __import__(modname) sys.modules[modname].remove(mlist) - REMOVABLES = [ - (os.path.join('lists', listname), _('list info')), - ] + removeables.append((os.path.join('lists', listname), _('list info'))) # Remove any stale locks associated with the list for filename in os.listdir(mm_cfg.LOCK_DIR): fn_listname = filename.split('.')[0] if fn_listname == listname: - REMOVABLES.append((os.path.join(mm_cfg.LOCK_DIR, filename), - _('stale lock file'))) + removeables.append((os.path.join(mm_cfg.LOCK_DIR, filename), + _('stale lock file'))) - if removeArchives: - REMOVABLES.extend([ + if opts.archives: + removeables.extend([ (os.path.join('archives', 'private', listname), _('private archives')), (os.path.join('archives', 'private', listname + '.mbox'), @@ -143,9 +115,9 @@ def main(): _('public archives')), ]) - for dirtmpl, msg in REMOVABLES: - dir = os.path.join(mm_cfg.VAR_PREFIX, dirtmpl) - remove_it(listname, dir, msg) + for dirtmpl, msg in removeables: + path = os.path.join(mm_cfg.VAR_PREFIX, dirtmpl) + remove_it(listname, path, msg) diff --git a/Mailman/i18n.py b/Mailman/i18n.py index c913b2130..051d55249 100644 --- a/Mailman/i18n.py +++ b/Mailman/i18n.py @@ -19,6 +19,8 @@ import sys import time import gettext +from string import Template + from Mailman import mm_cfg from Mailman.SafeDict import SafeDict @@ -38,9 +40,11 @@ def set_language(language=None): # untranslated English. _translation = gettext.NullTranslations() + def get_translation(): return _translation + def set_translation(translation): global _translation _translation = translation @@ -68,25 +72,32 @@ def _(s): # and have it Just Work. Note that the lookup order for keys in the # original string is 1) locals dictionary, 2) globals dictionary. # - # First, get the frame of the caller + # We inspect the frame's globals to see if __i18n_templates__ is set. If + # so, we use string.Template style $-variables instead of more traditional + # %-strings. + # + # Get the frame of the caller frame = sys._getframe(1) # A `safe' dictionary is used so we won't get an exception if there's a # missing key in the dictionary. - dict = SafeDict(frame.f_globals.copy()) - dict.update(frame.f_locals) + substitutions = SafeDict(frame.f_globals.copy()) + substitutions.update(frame.f_locals) # Translating the string returns an encoded 8-bit string. Rather than # turn that into a Unicode, we turn any Unicodes in the dictionary values - # into encoded 8-bit strings. BAW: Returning a Unicode here broke too + # into encoded 8-bit strings. XXX: Returning a Unicode here broke too # much other stuff and _() has many tentacles. Eventually I think we want # to use Unicode everywhere. tns = _translation.gettext(s) charset = _translation.charset() if not charset: charset = 'us-ascii' - for k, v in dict.items(): + for k, v in substitutions.items(): if isinstance(v, unicode): - dict[k] = v.encode(charset, 'replace') - return tns % dict + substitutions[k] = v.encode(charset, 'replace') + # Are we using $-strings or %-strings? + if substitutions.get('__i18n_templates__', False): + return Template(tns).substitute(substitutions) + return tns % substitutions @@ -137,7 +148,7 @@ def ctime(date): break else: year, mon, day, hh, mm, ss, wday, yday, dst = time.localtime(date) - if dst in (0,1): + if dst in (0, 1): tzname = time.tzname[dst] wday = daysofweek[wday] diff --git a/Mailman/loginit.py b/Mailman/loginit.py index a0a0699e3..e98593d02 100644 --- a/Mailman/loginit.py +++ b/Mailman/loginit.py @@ -37,22 +37,37 @@ _handlers = [] -class ReopenableFileHandler(logging.FileHandler): - def __init__(self, filename, mode='a', encoding=None): - # Unfortunately, FileHandler's __init__() doesn't store encoding. - logging.FileHandler.__init__(self, filename, mode, encoding) - self.encoding = encoding +class ReopenableFileHandler(logging.Handler): + def __init__(self, filename): + self._filename = filename + self._stream = self._open() + logging.Handler.__init__(self) - def reopen(self): - # Flush and close the file/stream, then reopen it. WIBNI the base - # FileHandler supported this? + def _open(self): + return codecs.open(self._filename, 'a', 'utf-8') + + def flush(self): + self._stream.flush() + + def emit(self, record): + try: + msg = self.format(record) + try: + self._stream.write(msg) + except UnicodeError: + self._stream.write(msg.encode('string-escape')) + self.flush() + except: + self.handleError(record) + + def close(self): self.flush() - self.stream.close() - if self.encoding is None: - stream = open(self.baseFilename, self.mode) - else: - stream = codecs.open(self.baseFilename, mode, self.encoding) - self.stream = stream + self._stream.close() + logging.Handler.close(self) + + def reopen(self): + self._stream.close() + self._stream = self._open() |
