diff options
Diffstat (limited to 'mailman/attic/bin')
| -rwxr-xr-x | mailman/attic/bin/clone_member | 219 | ||||
| -rw-r--r-- | mailman/attic/bin/discard | 120 | ||||
| -rw-r--r-- | mailman/attic/bin/fix_url.py | 93 | ||||
| -rw-r--r-- | mailman/attic/bin/list_admins | 101 | ||||
| -rw-r--r-- | mailman/attic/bin/msgfmt.py | 203 | ||||
| -rw-r--r-- | mailman/attic/bin/po2templ.py | 90 | ||||
| -rw-r--r-- | mailman/attic/bin/pygettext.py | 545 | ||||
| -rwxr-xr-x | mailman/attic/bin/remove_members | 186 | ||||
| -rw-r--r-- | mailman/attic/bin/reset_pw.py | 83 | ||||
| -rwxr-xr-x | mailman/attic/bin/sync_members | 286 | ||||
| -rw-r--r-- | mailman/attic/bin/templ2pot.py | 120 | ||||
| -rwxr-xr-x | mailman/attic/bin/transcheck | 412 |
12 files changed, 0 insertions, 2458 deletions
diff --git a/mailman/attic/bin/clone_member b/mailman/attic/bin/clone_member deleted file mode 100755 index 1f2a03aca..000000000 --- a/mailman/attic/bin/clone_member +++ /dev/null @@ -1,219 +0,0 @@ -#! @PYTHON@ -# -# Copyright (C) 1998,1999,2000,2001,2002 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. - -"""Clone a member address. - -Cloning a member address means that a new member will be added who has all the -same options and passwords as the original member address. Note that this -operation is fairly trusting of the user who runs it -- it does no -verification to the new address, it does not send out a welcome message, etc. - -The existing member's subscription is usually not modified in any way. If you -want to remove the old address, use the -r flag. If you also want to change -any list admin addresses, use the -a flag. - -Usage: - clone_member [options] fromoldaddr tonewaddr - -Where: - - --listname=listname - -l listname - Check and modify only the named mailing lists. If -l is not given, - then all mailing lists are scanned from the address. Multiple -l - options can be supplied. - - --remove - -r - Remove the old address from the mailing list after it's been cloned. - - --admin - -a - Scan the list admin addresses for the old address, and clone or change - them too. - - --quiet - -q - Do the modifications quietly. - - --nomodify - -n - Print what would be done, but don't actually do it. Inhibits the - --quiet flag. - - --help - -h - Print this help message and exit. - - fromoldaddr (`from old address') is the old address of the user. tonewaddr - (`to new address') is the new address of the user. - -""" - -import sys -import getopt - -import paths -from Mailman import MailList -from Mailman import Utils -from Mailman import Errors -from Mailman.i18n import _ - - - -def usage(code, msg=''): - if code: - fd = sys.stderr - else: - fd = sys.stdout - print >> fd, _(__doc__) - if msg: - print >> fd, msg - sys.exit(code) - - - -def dolist(mlist, options): - SPACE = ' ' - if not options.quiet: - print _('processing mailing list:'), mlist.internal_name() - - # scan the list owners. TBD: mlist.owner keys should be lowercase? - oldowners = mlist.owner[:] - oldowners.sort() - if options.admintoo: - if not options.quiet: - print _(' scanning list owners:'), SPACE.join(oldowners) - newowners = {} - foundp = 0 - for owner in mlist.owner: - if options.lfromaddr == owner.lower(): - foundp = 1 - if options.remove: - continue - newowners[owner] = 1 - if foundp: - newowners[options.toaddr] = 1 - newowners = newowners.keys() - newowners.sort() - if options.modify: - mlist.owner = newowners - if not options.quiet: - if newowners <> oldowners: - print - print _(' new list owners:'), SPACE.join(newowners) - else: - print _('(no change)') - - # see if the fromaddr is a digest member or regular member - if options.lfromaddr in mlist.getDigestMemberKeys(): - digest = 1 - elif options.lfromaddr in mlist.getRegularMemberKeys(): - digest = 0 - else: - if not options.quiet: - print _(' address not found:'), options.fromaddr - return - - # Now change the membership address - try: - if options.modify: - mlist.changeMemberAddress(options.fromaddr, options.toaddr, - not options.remove) - if not options.quiet: - print _(' clone address added:'), options.toaddr - except Errors.MMAlreadyAMember: - if not options.quiet: - print _(' clone address is already a member:'), options.toaddr - - if options.remove: - print _(' original address removed:'), options.fromaddr - - - -def main(): - # default options - class Options: - listnames = None - remove = 0 - admintoo = 0 - quiet = 0 - modify = 1 - - # scan sysargs - try: - opts, args = getopt.getopt( - sys.argv[1:], 'arl:qnh', - ['admin', 'remove', 'listname=', 'quiet', 'nomodify', 'help']) - except getopt.error, msg: - usage(1, msg) - - options = Options() - for opt, arg in opts: - if opt in ('-h', '--help'): - usage(0) - elif opt in ('-q', '--quiet'): - options.quiet = 1 - elif opt in ('-n', '--nomodify'): - options.modify = 0 - elif opt in ('-a', '--admin'): - options.admintoo = 1 - elif opt in ('-r', '--remove'): - options.remove = 1 - elif opt in ('-l', '--listname'): - if options.listnames is None: - options.listnames = [] - options.listnames.append(arg.lower()) - - # further options and argument processing - if not options.modify: - options.quiet = 0 - - if len(args) <> 2: - usage(1) - fromaddr = args[0] - toaddr = args[1] - - # validate and normalize the target address - try: - Utils.ValidateEmail(toaddr) - except Errors.EmailAddressError: - usage(1, _('Not a valid email address: %(toaddr)s')) - lfromaddr = fromaddr.lower() - options.toaddr = toaddr - options.fromaddr = fromaddr - options.lfromaddr = lfromaddr - - if options.listnames is None: - options.listnames = Utils.list_names() - - for listname in options.listnames: - try: - mlist = MailList.MailList(listname) - except Errors.MMListError, e: - print _('Error opening list "%(listname)s", skipping.\n%(e)s') - continue - try: - dolist(mlist, options) - finally: - mlist.Save() - mlist.Unlock() - - -if __name__ == '__main__': - main() diff --git a/mailman/attic/bin/discard b/mailman/attic/bin/discard deleted file mode 100644 index c30198441..000000000 --- a/mailman/attic/bin/discard +++ /dev/null @@ -1,120 +0,0 @@ -#! @PYTHON@ -# -# Copyright (C) 2003 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. - -"""Discard held messages. - -Usage: - discard [options] file ... - -Options: - --help / -h - Print this help message and exit. - - --quiet / -q - Don't print status messages. -""" - -# TODO: add command line arguments for specifying other actions than DISCARD, -# and also for specifying other __handlepost() arguments, i.e. comment, -# preserve, forward, addr - -import os -import re -import sys -import getopt - -import paths -from Mailman import mm_cfg -from Mailman.MailList import MailList -from Mailman.i18n import _ - -try: - True, False -except NameError: - True = 1 - False = 0 - -cre = re.compile(r'heldmsg-(?P<listname>.*)-(?P<id>[0-9]+)\.(pck|txt)$') - - - -def usage(code, msg=''): - if code: - fd = sys.stderr - else: - fd = sys.stdout - print >> fd, _(__doc__) - if msg: - print >> fd, msg - sys.exit(code) - - - -def main(): - try: - opts, args = getopt.getopt(sys.argv[1:], 'hq', ['help', 'quiet']) - except getopt.error, msg: - usage(1, msg) - - quiet = False - for opt, arg in opts: - if opt in ('-h', '--help'): - usage(0) - elif opt in ('-q', '--quiet'): - quiet = True - - files = args - if not files: - print _('Nothing to do.') - - # Mapping from listnames to sequence of request ids - discards = {} - - # Cruise through all the named files, collating by mailing list. We'll - # lock the list once, process all holds for that list and move on. - for f in files: - basename = os.path.basename(f) - mo = cre.match(basename) - if not mo: - print >> sys.stderr, _('Ignoring non-held message: %(f)s') - continue - listname, id = mo.group('listname', 'id') - try: - id = int(id) - except (ValueError, TypeError): - print >> sys.stderr, _('Ignoring held msg w/bad id: %(f)s') - continue - discards.setdefault(listname, []).append(id) - - # Now do the discards - for listname, ids in discards.items(): - mlist = MailList(listname) - try: - for id in ids: - # No comment, no preserve, no forward, no forwarding address - mlist.HandleRequest(id, mm_cfg.DISCARD, '', False, False, '') - if not quiet: - print _('Discarded held msg #%(id)s for list %(listname)s') - mlist.Save() - finally: - mlist.Unlock() - - - -if __name__ == '__main__': - main() diff --git a/mailman/attic/bin/fix_url.py b/mailman/attic/bin/fix_url.py deleted file mode 100644 index 30618a1a3..000000000 --- a/mailman/attic/bin/fix_url.py +++ /dev/null @@ -1,93 +0,0 @@ -#! @PYTHON@ -# -# Copyright (C) 2001-2009 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. - -"""Reset a list's web_page_url attribute to the default setting. - -This script is intended to be run as a bin/withlist script, i.e. - -% bin/withlist -l -r fix_url listname [options] - -Options: - -u urlhost - --urlhost=urlhost - Look up urlhost in the virtual host table and set the web_page_url and - host_name attributes of the list to the values found. This - essentially moves the list from one virtual domain to another. - - Without this option, the default web_page_url and host_name values are - used. - - -v / --verbose - Print what the script is doing. - -If run standalone, it prints this help text and exits. -""" - -import sys -import getopt - -import paths -from Mailman.configuration import config -from Mailman.i18n import _ - - - -def usage(code, msg=''): - print _(__doc__.replace('%', '%%')) - if msg: - print msg - sys.exit(code) - - - -def fix_url(mlist, *args): - try: - opts, args = getopt.getopt(args, 'u:v', ['urlhost=', 'verbose']) - except getopt.error, msg: - usage(1, msg) - - verbose = 0 - urlhost = mailhost = None - for opt, arg in opts: - if opt in ('-u', '--urlhost'): - urlhost = arg - elif opt in ('-v', '--verbose'): - verbose = 1 - - if urlhost: - web_page_url = config.DEFAULT_URL_PATTERN % urlhost - mailhost = config.VIRTUAL_HOSTS.get(urlhost.lower(), urlhost) - else: - web_page_url = config.DEFAULT_URL_PATTERN % config.DEFAULT_URL_HOST - mailhost = config.DEFAULT_EMAIL_HOST - - if verbose: - print _('Setting web_page_url to: %(web_page_url)s') - mlist.web_page_url = web_page_url - if verbose: - print _('Setting host_name to: %(mailhost)s') - mlist.host_name = mailhost - print _('Saving list') - mlist.Save() - mlist.Unlock() - - - -if __name__ == '__main__': - usage(0) diff --git a/mailman/attic/bin/list_admins b/mailman/attic/bin/list_admins deleted file mode 100644 index c628a42dc..000000000 --- a/mailman/attic/bin/list_admins +++ /dev/null @@ -1,101 +0,0 @@ -#! @PYTHON@ -# -# Copyright (C) 2001,2002 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. - -"""List all the owners of a mailing list. - -Usage: %(program)s [options] listname ... - -Where: - - --all-vhost=vhost - -v=vhost - List the owners of all the mailing lists for the given virtual host. - - --all - -a - List the owners of all the mailing lists on this system. - - --help - -h - Print this help message and exit. - -`listname' is the name of the mailing list to print the owners of. You can -have more than one named list on the command line. -""" - -import sys -import getopt - -import paths -from Mailman import MailList, Utils -from Mailman import Errors -from Mailman.i18n import _ - -COMMASPACE = ', ' - -program = sys.argv[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) - - - -def main(): - try: - opts, args = getopt.getopt(sys.argv[1:], 'hv:a', - ['help', 'all-vhost=', 'all']) - except getopt.error, msg: - usage(1, msg) - - listnames = args - vhost = None - for opt, arg in opts: - if opt in ('-h', '--help'): - usage(0) - elif opt in ('-a', '--all'): - listnames = Utils.list_names() - elif opt in ('-v', '--all-vhost'): - listnames = Utils.list_names() - vhost = arg - - for listname in listnames: - try: - mlist = MailList.MailList(listname, lock=0) - except Errors.MMListError, e: - print _('No such list: %(listname)s') - continue - - if vhost and vhost <> mlist.host_name: - continue - - owners = COMMASPACE.join(mlist.owner) - print _('List: %(listname)s, \tOwners: %(owners)s') - - - -if __name__ == '__main__': - main() diff --git a/mailman/attic/bin/msgfmt.py b/mailman/attic/bin/msgfmt.py deleted file mode 100644 index 8a2d4e66e..000000000 --- a/mailman/attic/bin/msgfmt.py +++ /dev/null @@ -1,203 +0,0 @@ -#! /usr/bin/env python -# -*- coding: iso-8859-1 -*- -# Written by Martin v. Löwis <loewis@informatik.hu-berlin.de> - -"""Generate binary message catalog from textual translation description. - -This program converts a textual Uniforum-style message catalog (.po file) into -a binary GNU catalog (.mo file). This is essentially the same function as the -GNU msgfmt program, however, it is a simpler implementation. - -Usage: msgfmt.py [OPTIONS] filename.po - -Options: - -o file - --output-file=file - Specify the output file to write to. If omitted, output will go to a - file named filename.mo (based off the input file name). - - -h - --help - Print this message and exit. - - -V - --version - Display version information and exit. -""" - -import sys -import os -import getopt -import struct -import array - -__version__ = "1.1" - -MESSAGES = {} - - - -def usage(code, msg=''): - print >> sys.stderr, __doc__ - if msg: - print >> sys.stderr, msg - sys.exit(code) - - - -def add(id, str, fuzzy): - "Add a non-fuzzy translation to the dictionary." - global MESSAGES - if not fuzzy and str: - MESSAGES[id] = str - - - -def generate(): - "Return the generated output." - global MESSAGES - keys = MESSAGES.keys() - # the keys are sorted in the .mo file - keys.sort() - offsets = [] - ids = strs = '' - for id in keys: - # For each string, we need size and file offset. Each string is NUL - # terminated; the NUL does not count into the size. - offsets.append((len(ids), len(id), len(strs), len(MESSAGES[id]))) - ids += id + '\0' - strs += MESSAGES[id] + '\0' - output = '' - # The header is 7 32-bit unsigned integers. We don't use hash tables, so - # the keys start right after the index tables. - # translated string. - keystart = 7*4+16*len(keys) - # and the values start after the keys - valuestart = keystart + len(ids) - koffsets = [] - voffsets = [] - # The string table first has the list of keys, then the list of values. - # Each entry has first the size of the string, then the file offset. - for o1, l1, o2, l2 in offsets: - koffsets += [l1, o1+keystart] - voffsets += [l2, o2+valuestart] - offsets = koffsets + voffsets - output = struct.pack("Iiiiiii", - 0x950412deL, # Magic - 0, # Version - len(keys), # # of entries - 7*4, # start of key index - 7*4+len(keys)*8, # start of value index - 0, 0) # size and offset of hash table - output += array.array("i", offsets).tostring() - output += ids - output += strs - return output - - - -def make(filename, outfile): - ID = 1 - STR = 2 - - # Compute .mo name from .po name and arguments - if filename.endswith('.po'): - infile = filename - else: - infile = filename + '.po' - if outfile is None: - outfile = os.path.splitext(infile)[0] + '.mo' - - try: - lines = open(infile).readlines() - except IOError, msg: - print >> sys.stderr, msg - sys.exit(1) - - section = None - fuzzy = 0 - - # Parse the catalog - lno = 0 - for l in lines: - lno += 1 - # If we get a comment line after a msgstr, this is a new entry - if l[0] == '#' and section == STR: - add(msgid, msgstr, fuzzy) - section = None - fuzzy = 0 - # Record a fuzzy mark - if l[:2] == '#,' and l.find('fuzzy'): - fuzzy = 1 - # Skip comments - if l[0] == '#': - continue - # Now we are in a msgid section, output previous section - if l.startswith('msgid'): - if section == STR: - add(msgid, msgstr, fuzzy) - section = ID - l = l[5:] - msgid = msgstr = '' - # Now we are in a msgstr section - elif l.startswith('msgstr'): - section = STR - l = l[6:] - # Skip empty lines - l = l.strip() - if not l: - continue - # XXX: Does this always follow Python escape semantics? - l = eval(l) - if section == ID: - msgid += l - elif section == STR: - msgstr += l - else: - print >> sys.stderr, 'Syntax error on %s:%d' % (infile, lno), \ - 'before:' - print >> sys.stderr, l - sys.exit(1) - # Add last entry - if section == STR: - add(msgid, msgstr, fuzzy) - - # Compute output - output = generate() - - try: - open(outfile,"wb").write(output) - except IOError,msg: - print >> sys.stderr, msg - - - -def main(): - try: - opts, args = getopt.getopt(sys.argv[1:], 'hVo:', - ['help', 'version', 'output-file=']) - except getopt.error, msg: - usage(1, msg) - - outfile = None - # parse options - for opt, arg in opts: - if opt in ('-h', '--help'): - usage(0) - elif opt in ('-V', '--version'): - print >> sys.stderr, "msgfmt.py", __version__ - sys.exit(0) - elif opt in ('-o', '--output-file'): - outfile = arg - # do it - if not args: - print >> sys.stderr, 'No input file given' - print >> sys.stderr, "Try `msgfmt --help' for more information." - return - - for filename in args: - make(filename, outfile) - - -if __name__ == '__main__': - main() diff --git a/mailman/attic/bin/po2templ.py b/mailman/attic/bin/po2templ.py deleted file mode 100644 index 86eae96b9..000000000 --- a/mailman/attic/bin/po2templ.py +++ /dev/null @@ -1,90 +0,0 @@ -#! @PYTHON@ -# -# Copyright (C) 2005-2009 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. - -# Author: Tokio Kikuchi <tkikuchi@is.kochi-u.ac.jp> - - -"""po2templ.py - -Extract templates from language po file. - -Usage: po2templ.py languages -""" - -import re -import sys - -cre = re.compile('^#:\s*templates/en/(?P<filename>.*?):1') - - - -def do_lang(lang): - in_template = False - in_msg = False - msgstr = '' - fp = file('messages/%s/LC_MESSAGES/mailman.po' % lang) - try: - for line in fp: - m = cre.search(line) - if m: - in_template = True - in_msg = False - filename = m.group('filename') - outfilename = 'templates/%s/%s' % (lang, filename) - continue - if in_template and line.startswith('#,'): - if line.strip() == '#, fuzzy': - in_template = False - continue - if in_template and line.startswith('msgstr'): - line = line[7:] - in_msg = True - if in_msg: - if not line.strip(): - in_template = False - in_msg = False - if len(msgstr) > 1 and outfilename: - # exclude no translation ... 1 is for LF only - outfile = file(outfilename, 'w') - try: - outfile.write(msgstr) - outfile.write('\n') - finally: - outfile.close() - outfilename = '' - msgstr = '' - continue - msgstr += eval(line) - finally: - fp.close() - if len(msgstr) > 1 and outfilename: - # flush remaining msgstr (last template file) - outfile = file(outfilename, 'w') - try: - outfile.write(msgstr) - outfile.write('\n') - finally: - outfile.close() - - - -if __name__ == '__main__': - langs = sys.argv[1:] - for lang in langs: - do_lang(lang) diff --git a/mailman/attic/bin/pygettext.py b/mailman/attic/bin/pygettext.py deleted file mode 100644 index 84421ee8c..000000000 --- a/mailman/attic/bin/pygettext.py +++ /dev/null @@ -1,545 +0,0 @@ -#! @PYTHON@ -# Originally written by Barry Warsaw <barry@zope.com> -# -# Minimally patched to make it even more xgettext compatible -# by Peter Funk <pf@artcom-gmbh.de> - -"""pygettext -- Python equivalent of xgettext(1) - -Many systems (Solaris, Linux, Gnu) provide extensive tools that ease the -internationalization of C programs. Most of these tools are independent of -the programming language and can be used from within Python programs. Martin -von Loewis' work[1] helps considerably in this regard. - -There's one problem though; xgettext is the program that scans source code -looking for message strings, but it groks only C (or C++). Python introduces -a few wrinkles, such as dual quoting characters, triple quoted strings, and -raw strings. xgettext understands none of this. - -Enter pygettext, which uses Python's standard tokenize module to scan Python -source code, generating .pot files identical to what GNU xgettext[2] generates -for C and C++ code. From there, the standard GNU tools can be used. - -A word about marking Python strings as candidates for translation. GNU -xgettext recognizes the following keywords: gettext, dgettext, dcgettext, and -gettext_noop. But those can be a lot of text to include all over your code. -C and C++ have a trick: they use the C preprocessor. Most internationalized C -source includes a #define for gettext() to _() so that what has to be written -in the source is much less. Thus these are both translatable strings: - - gettext("Translatable String") - _("Translatable String") - -Python of course has no preprocessor so this doesn't work so well. Thus, -pygettext searches only for _() by default, but see the -k/--keyword flag -below for how to augment this. - - [1] http://www.python.org/workshops/1997-10/proceedings/loewis.html - [2] http://www.gnu.org/software/gettext/gettext.html - -NOTE: pygettext attempts to be option and feature compatible with GNU xgettext -where ever possible. However some options are still missing or are not fully -implemented. Also, xgettext's use of command line switches with option -arguments is broken, and in these cases, pygettext just defines additional -switches. - -Usage: pygettext [options] inputfile ... - -Options: - - -a - --extract-all - Extract all strings. - - -d name - --default-domain=name - Rename the default output file from messages.pot to name.pot. - - -E - --escape - Replace non-ASCII characters with octal escape sequences. - - -D - --docstrings - Extract module, class, method, and function docstrings. These do not - need to be wrapped in _() markers, and in fact cannot be for Python to - consider them docstrings. (See also the -X option). - - -h - --help - Print this help message and exit. - - -k word - --keyword=word - Keywords to look for in addition to the default set, which are: - %(DEFAULTKEYWORDS)s - - You can have multiple -k flags on the command line. - - -K - --no-default-keywords - Disable the default set of keywords (see above). Any keywords - explicitly added with the -k/--keyword option are still recognized. - - --no-location - Do not write filename/lineno location comments. - - -n - --add-location - Write filename/lineno location comments indicating where each - extracted string is found in the source. These lines appear before - each msgid. The style of comments is controlled by the -S/--style - option. This is the default. - - -o filename - --output=filename - Rename the default output file from messages.pot to filename. If - filename is `-' then the output is sent to standard out. - - -p dir - --output-dir=dir - Output files will be placed in directory dir. - - -S stylename - --style stylename - Specify which style to use for location comments. Two styles are - supported: - - Solaris # File: filename, line: line-number - GNU #: filename:line - - The style name is case insensitive. GNU style is the default. - - -v - --verbose - Print the names of the files being processed. - - -V - --version - Print the version of pygettext and exit. - - -w columns - --width=columns - Set width of output to columns. - - -x filename - --exclude-file=filename - Specify a file that contains a list of strings that are not be - extracted from the input files. Each string to be excluded must - appear on a line by itself in the file. - - -X filename - --no-docstrings=filename - Specify a file that contains a list of files (one per line) that - should not have their docstrings extracted. This is only useful in - conjunction with the -D option above. - -If `inputfile' is -, standard input is read. -""" - -import os -import sys -import time -import getopt -import tokenize -import operator - -# for selftesting -try: - import fintl - _ = fintl.gettext -except ImportError: - def _(s): return s - -__version__ = '1.4' - -default_keywords = ['_'] -DEFAULTKEYWORDS = ', '.join(default_keywords) - -EMPTYSTRING = '' - - - -# The normal pot-file header. msgmerge and Emacs's po-mode work better if it's -# there. -pot_header = _('''\ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR ORGANIZATION -# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. -# -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\\n" -"POT-Creation-Date: %(time)s\\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n" -"Last-Translator: FULL NAME <EMAIL@ADDRESS>\\n" -"Language-Team: LANGUAGE <LL@li.org>\\n" -"MIME-Version: 1.0\\n" -"Content-Type: text/plain; charset=CHARSET\\n" -"Content-Transfer-Encoding: ENCODING\\n" -"Generated-By: pygettext.py %(version)s\\n" - -''') - - -def usage(code, msg=''): - if code: - fd = sys.stderr - else: - fd = sys.stdout - print >> fd, _(__doc__) % globals() - if msg: - print >> fd, msg - sys.exit(code) - - - -escapes = [] - -def make_escapes(pass_iso8859): - global escapes - if pass_iso8859: - # Allow iso-8859 characters to pass through so that e.g. 'msgid - # "H[o-umlaut]he"' would result not result in 'msgid "H\366he"'. - # Otherwise we escape any character outside the 32..126 range. - mod = 128 - else: - mod = 256 - for i in range(256): - if 32 <= (i % mod) <= 126: - escapes.append(chr(i)) - else: - escapes.append("\\%03o" % i) - escapes[ord('\\')] = '\\\\' - escapes[ord('\t')] = '\\t' - escapes[ord('\r')] = '\\r' - escapes[ord('\n')] = '\\n' - escapes[ord('\"')] = '\\"' - - -def escape(s): - global escapes - s = list(s) - for i in range(len(s)): - s[i] = escapes[ord(s[i])] - return EMPTYSTRING.join(s) - - -def safe_eval(s): - # unwrap quotes, safely - return eval(s, {'__builtins__':{}}, {}) - - -def normalize(s): - # This converts the various Python string types into a format that is - # appropriate for .po files, namely much closer to C style. - lines = s.split('\n') - if len(lines) == 1: - s = '"' + escape(s) + '"' - else: - if not lines[-1]: - del lines[-1] - lines[-1] = lines[-1] + '\n' - for i in range(len(lines)): - lines[i] = escape(lines[i]) - lineterm = '\\n"\n"' - s = '""\n"' + lineterm.join(lines) + '"' - return s - - - -class TokenEater: - def __init__(self, options): - self.__options = options - self.__messages = {} - self.__state = self.__waiting - self.__data = [] - self.__lineno = -1 - self.__freshmodule = 1 - self.__curfile = None - - def __call__(self, ttype, tstring, stup, etup, line): - # dispatch -## import token -## print >> sys.stderr, 'ttype:', token.tok_name[ttype], \ -## 'tstring:', tstring - self.__state(ttype, tstring, stup[0]) - - def __waiting(self, ttype, tstring, lineno): - opts = self.__options - # Do docstring extractions, if enabled - if opts.docstrings and not opts.nodocstrings.get(self.__curfile): - # module docstring? - if self.__freshmodule: - if ttype == tokenize.STRING: - self.__addentry(safe_eval(tstring), lineno, isdocstring=1) - self.__freshmodule = 0 - elif ttype not in (tokenize.COMMENT, tokenize.NL): - self.__freshmodule = 0 - return - # class docstring? - if ttype == tokenize.NAME and tstring in ('class', 'def'): - self.__state = self.__suiteseen - return - if ttype == tokenize.NAME and tstring in opts.keywords: - self.__state = self.__keywordseen - - def __suiteseen(self, ttype, tstring, lineno): - # ignore anything until we see the colon - if ttype == tokenize.OP and tstring == ':': - self.__state = self.__suitedocstring - - def __suitedocstring(self, ttype, tstring, lineno): - # ignore any intervening noise - if ttype == tokenize.STRING: - self.__addentry(safe_eval(tstring), lineno, isdocstring=1) - self.__state = self.__waiting - elif ttype not in (tokenize.NEWLINE, tokenize.INDENT, - tokenize.COMMENT): - # there was no class docstring - self.__state = self.__waiting - - def __keywordseen(self, ttype, tstring, lineno): - if ttype == tokenize.OP and tstring == '(': - self.__data = [] - self.__lineno = lineno - self.__state = self.__openseen - else: - self.__state = self.__waiting - - def __openseen(self, ttype, tstring, lineno): - if ttype == tokenize.OP and tstring == ')': - # We've seen the last of the translatable strings. Record the - # line number of the first line of the strings and update the list - # of messages seen. Reset state for the next batch. If there - # were no strings inside _(), then just ignore this entry. - if self.__data: - self.__addentry(EMPTYSTRING.join(self.__data)) - self.__state = self.__waiting - elif ttype == tokenize.STRING: - self.__data.append(safe_eval(tstring)) - # TBD: should we warn if we seen anything else? - - def __addentry(self, msg, lineno=None, isdocstring=0): - if lineno is None: - lineno = self.__lineno - if not msg in self.__options.toexclude: - entry = (self.__curfile, lineno) - self.__messages.setdefault(msg, {})[entry] = isdocstring - - def set_filename(self, filename): - self.__curfile = filename - self.__freshmodule = 1 - - def write(self, fp): - options = self.__options - timestamp = time.ctime(time.time()) - # The time stamp in the header doesn't have the same format as that - # generated by xgettext... - print >> fp, pot_header % {'time': timestamp, 'version': __version__} - # Sort the entries. First sort each particular entry's keys, then - # sort all the entries by their first item. - reverse = {} - for k, v in self.__messages.items(): - keys = v.keys() - keys.sort() - reverse.setdefault(tuple(keys), []).append((k, v)) - rkeys = reverse.keys() - rkeys.sort() - for rkey in rkeys: - rentries = reverse[rkey] - rentries.sort() - for k, v in rentries: - isdocstring = 0 - # If the entry was gleaned out of a docstring, then add a - # comment stating so. This is to aid translators who may wish - # to skip translating some unimportant docstrings. - if reduce(operator.__add__, v.values()): - isdocstring = 1 - # k is the message string, v is a dictionary-set of (filename, - # lineno) tuples. We want to sort the entries in v first by - # file name and then by line number. - v = v.keys() - v.sort() - if not options.writelocations: - pass - # location comments are different b/w Solaris and GNU: - elif options.locationstyle == options.SOLARIS: - for filename, lineno in v: - d = {'filename': filename, 'lineno': lineno} - print >>fp, _( - '# File: %(filename)s, line: %(lineno)d') % d - elif options.locationstyle == options.GNU: - # fit as many locations on one line, as long as the - # resulting line length doesn't exceeds 'options.width' - locline = '#:' - for filename, lineno in v: - d = {'filename': filename, 'lineno': lineno} - s = _(' %(filename)s:%(lineno)d') % d - if len(locline) + len(s) <= options.width: - locline = locline + s - else: - print >> fp, locline - locline = "#:" + s - if len(locline) > 2: - print >> fp, locline - if isdocstring: - print >> fp, '#, docstring' - print >> fp, 'msgid', normalize(k) - print >> fp, 'msgstr ""\n' - - - -def main(): - global default_keywords - try: - opts, args = getopt.getopt( - sys.argv[1:], - 'ad:DEhk:Kno:p:S:Vvw:x:X:', - ['extract-all', 'default-domain=', 'escape', 'help', - 'keyword=', 'no-default-keywords', - 'add-location', 'no-location', 'output=', 'output-dir=', - 'style=', 'verbose', 'version', 'width=', 'exclude-file=', - 'docstrings', 'no-docstrings', - ]) - except getopt.error, msg: - usage(1, msg) - - # for holding option values - class Options: - # constants - GNU = 1 - SOLARIS = 2 - # defaults - extractall = 0 # FIXME: currently this option has no effect at all. - escape = 0 - keywords = [] - outpath = '' - outfile = 'messages.pot' - writelocations = 1 - locationstyle = GNU - verbose = 0 - width = 78 - excludefilename = '' - docstrings = 0 - nodocstrings = {} - - options = Options() - locations = {'gnu' : options.GNU, - 'solaris' : options.SOLARIS, - } - - # parse options - for opt, arg in opts: - if opt in ('-h', '--help'): - usage(0) - elif opt in ('-a', '--extract-all'): - options.extractall = 1 - elif opt in ('-d', '--default-domain'): - options.outfile = arg + '.pot' - elif opt in ('-E', '--escape'): - options.escape = 1 - elif opt in ('-D', '--docstrings'): - options.docstrings = 1 - elif opt in ('-k', '--keyword'): - options.keywords.append(arg) - elif opt in ('-K', '--no-default-keywords'): - default_keywords = [] - elif opt in ('-n', '--add-location'): - options.writelocations = 1 - elif opt in ('--no-location',): - options.writelocations = 0 - elif opt in ('-S', '--style'): - options.locationstyle = locations.get(arg.lower()) - if options.locationstyle is None: - usage(1, _('Invalid value for --style: %s') % arg) - elif opt in ('-o', '--output'): - options.outfile = arg - elif opt in ('-p', '--output-dir'): - options.outpath = arg - elif opt in ('-v', '--verbose'): - options.verbose = 1 - elif opt in ('-V', '--version'): - print _('pygettext.py (xgettext for Python) %s') % __version__ - sys.exit(0) - elif opt in ('-w', '--width'): - try: - options.width = int(arg) - except ValueError: - usage(1, _('--width argument must be an integer: %s') % arg) - elif opt in ('-x', '--exclude-file'): - options.excludefilename = arg - elif opt in ('-X', '--no-docstrings'): - fp = open(arg) - try: - while 1: - line = fp.readline() - if not line: - break - options.nodocstrings[line[:-1]] = 1 - finally: - fp.close() - - # calculate escapes - make_escapes(options.escape) - - # calculate all keywords - options.keywords.extend(default_keywords) - - # initialize list of strings to exclude - if options.excludefilename: - try: - fp = open(options.excludefilename) - options.toexclude = fp.readlines() - fp.close() - except IOError: - print >> sys.stderr, _( - "Can't read --exclude-file: %s") % options.excludefilename - sys.exit(1) - else: - options.toexclude = [] - - # slurp through all the files - eater = TokenEater(options) - for filename in args: - if filename == '-': - if options.verbose: - print _('Reading standard input') - fp = sys.stdin - closep = 0 - else: - if options.verbose: - print _('Working on %s') % filename - fp = open(filename) - closep = 1 - try: - eater.set_filename(filename) - try: - tokenize.tokenize(fp.readline, eater) - except tokenize.TokenError, e: - print >> sys.stderr, '%s: %s, line %d, column %d' % ( - e[0], filename, e[1][0], e[1][1]) - finally: - if closep: - fp.close() - - # write the output - if options.outfile == '-': - fp = sys.stdout - closep = 0 - else: - if options.outpath: - options.outfile = os.path.join(options.outpath, options.outfile) - fp = open(options.outfile, 'w') - closep = 1 - try: - eater.write(fp) - finally: - if closep: - fp.close() - - -if __name__ == '__main__': - main() - # some more test strings - _(u'a unicode string') diff --git a/mailman/attic/bin/remove_members b/mailman/attic/bin/remove_members deleted file mode 100755 index a7b4ebb47..000000000 --- a/mailman/attic/bin/remove_members +++ /dev/null @@ -1,186 +0,0 @@ -#! @PYTHON@ -# -# Copyright (C) 1998-2005 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. - -"""Remove members from a list. - -Usage: - remove_members [options] [listname] [addr1 ...] - -Options: - - --file=file - -f file - Remove member addresses found in the given file. If file is - `-', read stdin. - - --all - -a - Remove all members of the mailing list. - (mutually exclusive with --fromall) - - --fromall - Removes the given addresses from all the lists on this system - regardless of virtual domains if you have any. This option cannot be - used -a/--all. Also, you should not specify a listname when using - this option. - - --nouserack - -n - Don't send the user acknowledgements. If not specified, the list - default value is used. - - --noadminack - -N - Don't send the admin acknowledgements. If not specified, the list - default value is used. - - --help - -h - Print this help message and exit. - - listname is the name of the mailing list to use. - - addr1 ... are additional addresses to remove. -""" - -import sys -import getopt - -import paths -from Mailman import MailList -from Mailman import Utils -from Mailman import Errors -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) - - -def ReadFile(filename): - lines = [] - if filename == "-": - fp = sys.stdin - closep = False - else: - fp = open(filename) - closep = True - lines = filter(None, [line.strip() for line in fp.readlines()]) - if closep: - fp.close() - return lines - - - -def main(): - try: - opts, args = getopt.getopt( - sys.argv[1:], 'naf:hN', - ['all', 'fromall', 'file=', 'help', 'nouserack', 'noadminack']) - except getopt.error, msg: - usage(1, msg) - - filename = None - all = False - alllists = False - # None means use list default - userack = None - admin_notif = None - - for opt, arg in opts: - if opt in ('-h', '--help'): - usage(0) - elif opt in ('-f', '--file'): - filename = arg - elif opt in ('-a', '--all'): - all = True - elif opt == '--fromall': - alllists = True - elif opt in ('-n', '--nouserack'): - userack = False - elif opt in ('-N', '--noadminack'): - admin_notif = False - - if len(args) < 1 and not (filename and alllists): - usage(1) - - # You probably don't want to delete all the users of all the lists -- Marc - if all and alllists: - usage(1) - - if alllists: - addresses = args - else: - listname = args[0].lower().strip() - addresses = args[1:] - - if alllists: - listnames = Utils.list_names() - else: - listnames = [listname] - - if filename: - try: - addresses = addresses + ReadFile(filename) - except IOError: - print _('Could not open file for reading: %(filename)s.') - - for listname in listnames: - try: - # open locked - mlist = MailList.MailList(listname) - except Errors.MMListError: - print _('Error opening list %(listname)s... skipping.') - continue - - if all: - addresses = mlist.getMembers() - - try: - for addr in addresses: - if not mlist.isMember(addr): - if not alllists: - print _('No such member: %(addr)s') - continue - mlist.ApprovedDeleteMember(addr, 'bin/remove_members', - admin_notif, userack) - if alllists: - print _("User `%(addr)s' removed from list: %(listname)s.") - mlist.Save() - finally: - mlist.Unlock() - - - -if __name__ == '__main__': - main() diff --git a/mailman/attic/bin/reset_pw.py b/mailman/attic/bin/reset_pw.py deleted file mode 100644 index 453c8b849..000000000 --- a/mailman/attic/bin/reset_pw.py +++ /dev/null @@ -1,83 +0,0 @@ -#! @PYTHON@ -# -# Copyright (C) 2004-2009 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. - -# Inspired by Florian Weimer. - -"""Reset the passwords for members of a mailing list. - -This script resets all the passwords of a mailing list's members. It can also -be used to reset the lists of all members of all mailing lists, but it is your -responsibility to let the users know that their passwords have been changed. - -This script is intended to be run as a bin/withlist script, i.e. - -% bin/withlist -l -r reset_pw listname [options] - -Options: - -v / --verbose - Print what the script is doing. -""" - -import sys -import getopt - -import paths -from Mailman import Utils -from Mailman.i18n import _ - - - -def usage(code, msg=''): - if code: - fd = sys.stderr - else: - fd = sys.stdout - print >> fd, _(__doc__.replace('%', '%%')) - if msg: - print >> fd, msg - sys.exit(code) - - - -def reset_pw(mlist, *args): - try: - opts, args = getopt.getopt(args, 'v', ['verbose']) - except getopt.error, msg: - usage(1, msg) - - verbose = False - for opt, args in opts: - if opt in ('-v', '--verbose'): - verbose = True - - listname = mlist.internal_name() - if verbose: - print _('Changing passwords for list: %(listname)s') - - for member in mlist.getMembers(): - randompw = Utils.MakeRandomPassword() - mlist.setMemberPassword(member, randompw) - if verbose: - print _('New password for member %(member)40s: %(randompw)s') - - mlist.Save() - - - -if __name__ == '__main__': - usage(0) diff --git a/mailman/attic/bin/sync_members b/mailman/attic/bin/sync_members deleted file mode 100755 index 4a21624c1..000000000 --- a/mailman/attic/bin/sync_members +++ /dev/null @@ -1,286 +0,0 @@ -#! @PYTHON@ -# -# Copyright (C) 1998-2003 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. - -"""Synchronize a mailing list's membership with a flat file. - -This script is useful if you have a Mailman mailing list and a sendmail -:include: style list of addresses (also as is used in Majordomo). For every -address in the file that does not appear in the mailing list, the address is -added. For every address in the mailing list that does not appear in the -file, the address is removed. Other options control what happens when an -address is added or removed. - -Usage: %(PROGRAM)s [options] -f file listname - -Where `options' are: - - --no-change - -n - Don't actually make the changes. Instead, print out what would be - done to the list. - - --welcome-msg[=<yes|no>] - -w[=<yes|no>] - Sets whether or not to send the newly added members a welcome - message, overriding whatever the list's `send_welcome_msg' setting - is. With -w=yes or -w, the welcome message is sent. With -w=no, no - message is sent. - - --goodbye-msg[=<yes|no>] - -g[=<yes|no>] - Sets whether or not to send the goodbye message to removed members, - overriding whatever the list's `send_goodbye_msg' setting is. With - -g=yes or -g, the goodbye message is sent. With -g=no, no message is - sent. - - --digest[=<yes|no>] - -d[=<yes|no>] - Selects whether to make newly added members receive messages in - digests. With -d=yes or -d, they become digest members. With -d=no - (or if no -d option given) they are added as regular members. - - --notifyadmin[=<yes|no>] - -a[=<yes|no>] - Specifies whether the admin should be notified for each subscription - or unsubscription. If you're adding a lot of addresses, you - definitely want to turn this off! With -a=yes or -a, the admin is - notified. With -a=no, the admin is not notified. With no -a option, - the default for the list is used. - - --file <filename | -> - -f <filename | -> - This option is required. It specifies the flat file to synchronize - against. Email addresses must appear one per line. If filename is - `-' then stdin is used. - - --help - -h - Print this message. - - listname - Required. This specifies the list to synchronize. -""" - -import sys - -import paths -# Import this /after/ paths so that the sys.path is properly hacked -import email.Utils - -from Mailman import MailList -from Mailman import Errors -from Mailman import Utils -from Mailman.UserDesc import UserDesc -from Mailman.i18n import _ - - - -PROGRAM = sys.argv[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) - - - -def yesno(opt): - i = opt.find('=') - yesno = opt[i+1:].lower() - if yesno in ('y', 'yes'): - return 1 - elif yesno in ('n', 'no'): - return 0 - else: - usage(1, _('Bad choice: %(yesno)s')) - # no return - - -def main(): - dryrun = 0 - digest = 0 - welcome = None - goodbye = None - filename = None - listname = None - notifyadmin = None - - # TBD: can't use getopt with this command line syntax, which is broken and - # should be changed to be getopt compatible. - i = 1 - while i < len(sys.argv): - opt = sys.argv[i] - if opt in ('-h', '--help'): - usage(0) - elif opt in ('-n', '--no-change'): - dryrun = 1 - i += 1 - print _('Dry run mode') - elif opt in ('-d', '--digest'): - digest = 1 - i += 1 - elif opt.startswith('-d=') or opt.startswith('--digest='): - digest = yesno(opt) - i += 1 - elif opt in ('-w', '--welcome-msg'): - welcome = 1 - i += 1 - elif opt.startswith('-w=') or opt.startswith('--welcome-msg='): - welcome = yesno(opt) - i += 1 - elif opt in ('-g', '--goodbye-msg'): - goodbye = 1 - i += 1 - elif opt.startswith('-g=') or opt.startswith('--goodbye-msg='): - goodbye = yesno(opt) - i += 1 - elif opt in ('-f', '--file'): - if filename is not None: - usage(1, _('Only one -f switch allowed')) - try: - filename = sys.argv[i+1] - except IndexError: - usage(1, _('No argument to -f given')) - i += 2 - elif opt in ('-a', '--notifyadmin'): - notifyadmin = 1 - i += 1 - elif opt.startswith('-a=') or opt.startswith('--notifyadmin='): - notifyadmin = yesno(opt) - i += 1 - elif opt[0] == '-': - usage(1, _('Illegal option: %(opt)s')) - else: - try: - listname = sys.argv[i].lower() - i += 1 - except IndexError: - usage(1, _('No listname given')) - break - - if listname is None or filename is None: - usage(1, _('Must have a listname and a filename')) - - # read the list of addresses to sync to from the file - if filename == '-': - filemembers = sys.stdin.readlines() - else: - try: - fp = open(filename) - except IOError, (code, msg): - usage(1, _('Cannot read address file: %(filename)s: %(msg)s')) - try: - filemembers = fp.readlines() - finally: - fp.close() - - # strip out lines we don't care about, they are comments (# in first - # non-whitespace) or are blank - for i in range(len(filemembers)-1, -1, -1): - addr = filemembers[i].strip() - if addr == '' or addr[:1] == '#': - del filemembers[i] - print _('Ignore : %(addr)30s') - - # first filter out any invalid addresses - filemembers = email.Utils.getaddresses(filemembers) - invalid = 0 - for name, addr in filemembers: - try: - Utils.ValidateEmail(addr) - except Errors.EmailAddressError: - print _('Invalid : %(addr)30s') - invalid = 1 - if invalid: - print _('You must fix the preceding invalid addresses first.') - sys.exit(1) - - # get the locked list object - try: - mlist = MailList.MailList(listname) - except Errors.MMListError, e: - print _('No such list: %(listname)s') - sys.exit(1) - - try: - # Get the list of addresses currently subscribed - addrs = {} - needsadding = {} - matches = {} - for addr in mlist.getMemberCPAddresses(mlist.getMembers()): - addrs[addr.lower()] = addr - - for name, addr in filemembers: - # Any address found in the file that is also in the list can be - # ignored. If not found in the list, it must be added later. - laddr = addr.lower() - if addrs.has_key(laddr): - del addrs[laddr] - matches[laddr] = 1 - elif not matches.has_key(laddr): - needsadding[laddr] = (name, addr) - - if not needsadding and not addrs: - print _('Nothing to do.') - sys.exit(0) - - enc = sys.getdefaultencoding() - # addrs contains now all the addresses that need removing - for laddr, (name, addr) in needsadding.items(): - pw = Utils.MakeRandomPassword() - # should not already be subscribed, otherwise our test above is - # broken. Bogosity is if the address is listed in the file more - # than once. Second and subsequent ones trigger an - # MMAlreadyAMember error. Just catch it and go on. - userdesc = UserDesc(addr, name, pw, digest) - try: - if not dryrun: - mlist.ApprovedAddMember(userdesc, welcome, notifyadmin) - s = email.Utils.formataddr((name, addr)).encode(enc, 'replace') - print _('Added : %(s)s') - except Errors.MMAlreadyAMember: - pass - - for laddr, addr in addrs.items(): - # Should be a member, otherwise our test above is broken - name = mlist.getMemberName(laddr) or '' - if not dryrun: - try: - mlist.ApprovedDeleteMember(addr, admin_notif=notifyadmin, - userack=goodbye) - except Errors.NotAMemberError: - # This can happen if the address is illegal (i.e. can't be - # parsed by email.Utils.parseaddr()) but for legacy - # reasons is in the database. Use a lower level remove to - # get rid of this member's entry - mlist.removeMember(addr) - s = email.Utils.formataddr((name, addr)).encode(enc, 'replace') - print _('Removed: %(s)s') - - mlist.Save() - finally: - mlist.Unlock() - - -if __name__ == '__main__': - main() diff --git a/mailman/attic/bin/templ2pot.py b/mailman/attic/bin/templ2pot.py deleted file mode 100644 index 0253cc2cd..000000000 --- a/mailman/attic/bin/templ2pot.py +++ /dev/null @@ -1,120 +0,0 @@ -#! @PYTHON@ -# Code stolen from pygettext.py -# by Tokio Kikuchi <tkikuchi@is.kochi-u.ac.jp> - -"""templ2pot.py -- convert mailman template (en) to pot format. - -Usage: templ2pot.py inputfile ... - -Options: - - -h, --help - -Inputfiles are english templates. Outputs are written to stdout. -""" - -import sys -import getopt - - - -try: - import paths - from Mailman.i18n import _ -except ImportError: - def _(s): return s - -EMPTYSTRING = '' - - - -def usage(code, msg=''): - if code: - fd = sys.stderr - else: - fd = sys.stdout - print >> fd, _(__doc__) % globals() - if msg: - print >> fd, msg - sys.exit(code) - - - -escapes = [] - -def make_escapes(pass_iso8859): - global escapes - if pass_iso8859: - # Allow iso-8859 characters to pass through so that e.g. 'msgid - # "H[o-umlaut]he"' would result not result in 'msgid "H\366he"'. - # Otherwise we escape any character outside the 32..126 range. - mod = 128 - else: - mod = 256 - for i in range(256): - if 32 <= (i % mod) <= 126: - escapes.append(chr(i)) - else: - escapes.append("\\%03o" % i) - escapes[ord('\\')] = '\\\\' - escapes[ord('\t')] = '\\t' - escapes[ord('\r')] = '\\r' - escapes[ord('\n')] = '\\n' - escapes[ord('\"')] = '\\"' - - -def escape(s): - global escapes - s = list(s) - for i in range(len(s)): - s[i] = escapes[ord(s[i])] - return EMPTYSTRING.join(s) - - -def normalize(s): - # This converts the various Python string types into a format that is - # appropriate for .po files, namely much closer to C style. - lines = s.splitlines() - if len(lines) == 1: - s = '"' + escape(s) + '"' - else: - if not lines[-1]: - del lines[-1] - lines[-1] = lines[-1] + '\n' - for i in range(len(lines)): - lines[i] = escape(lines[i]) - lineterm = '\\n"\n"' - s = '""\n"' + lineterm.join(lines) + '"' - return s - - - -def main(): - try: - opts, args = getopt.getopt( - sys.argv[1:], - 'h', - ['help',] - ) - except getopt.error, msg: - usage(1, msg) - - # parse options - for opt, arg in opts: - if opt in ('-h', '--help'): - usage(0) - - # calculate escapes - make_escapes(0) - - for filename in args: - print '#: %s:1' % filename - s = file(filename).read() - print '#, template' - print 'msgid', normalize(s) - print 'msgstr ""\n' - - - -if __name__ == '__main__': - main() diff --git a/mailman/attic/bin/transcheck b/mailman/attic/bin/transcheck deleted file mode 100755 index 73910e771..000000000 --- a/mailman/attic/bin/transcheck +++ /dev/null @@ -1,412 +0,0 @@ -#! @PYTHON@ -# -# transcheck - (c) 2002 by Simone Piunno <pioppo@ferrara.linux.it> -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the version 2.0 of the GNU General Public License as -# published by the Free Software Foundation. -# -# 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. - -""" -Check a given Mailman translation, making sure that variables and -tags referenced in translation are the same variables and tags in -the original templates and catalog. - -Usage: - -cd $MAILMAN_DIR -%(program)s [-q] <lang> - -Where <lang> is your country code (e.g. 'it' for Italy) and -q is -to ask for a brief summary. -""" - -import sys -import re -import os -import getopt - -import paths -from Mailman.i18n import _ - -program = sys.argv[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) - - - -class TransChecker: - "check a translation comparing with the original string" - def __init__(self, regexp, escaped=None): - self.dict = {} - self.errs = [] - self.regexp = re.compile(regexp) - self.escaped = None - if escaped: - self.escaped = re.compile(escaped) - - def checkin(self, string): - "scan a string from the original file" - for key in self.regexp.findall(string): - if self.escaped and self.escaped.match(key): - continue - if self.dict.has_key(key): - self.dict[key] += 1 - else: - self.dict[key] = 1 - - def checkout(self, string): - "scan a translated string" - for key in self.regexp.findall(string): - if self.escaped and self.escaped.match(key): - continue - if self.dict.has_key(key): - self.dict[key] -= 1 - else: - self.errs.append( - "%(key)s was not found" % - { 'key' : key } - ) - - def computeErrors(self): - "check for differences between checked in and checked out" - for key in self.dict.keys(): - if self.dict[key] < 0: - self.errs.append( - "Too much %(key)s" % - { 'key' : key } - ) - if self.dict[key] > 0: - self.errs.append( - "Too few %(key)s" % - { 'key' : key } - ) - return self.errs - - def status(self): - if self.errs: - return "FAILED" - else: - return "OK" - - def errorsAsString(self): - msg = "" - for err in self.errs: - msg += " - %(err)s" % { 'err': err } - return msg - - def reset(self): - self.dict = {} - self.errs = [] - - - -class POParser: - "parse a .po file extracting msgids and msgstrs" - def __init__(self, filename=""): - self.status = 0 - self.files = [] - self.msgid = "" - self.msgstr = "" - self.line = 1 - self.f = None - self.esc = { "n": "\n", "r": "\r", "t": "\t" } - if filename: - self.f = open(filename) - - def open(self, filename): - self.f = open(filename) - - def close(self): - self.f.close() - - def parse(self): - """States table for the finite-states-machine parser: - 0 idle - 1 filename-or-comment - 2 msgid - 3 msgstr - 4 end - """ - # each time we can safely re-initialize those vars - self.files = [] - self.msgid = "" - self.msgstr = "" - - - # can't continue if status == 4, this is a dead status - if self.status == 4: - return 0 - - while 1: - # continue scanning, char-by-char - c = self.f.read(1) - if not c: - # EOF -> maybe we have a msgstr to save? - self.status = 4 - if self.msgstr: - return 1 - else: - return 0 - - # keep the line count up-to-date - if c == "\n": - self.line += 1 - - # a pound was detected the previous char... - if self.status == 1: - if c == ":": - # was a line of filenames - row = self.f.readline() - self.files += row.split() - self.line += 1 - elif c == "\n": - # was a single pount on the line - pass - else: - # was a comment... discard - self.f.readline() - self.line += 1 - # in every case, we switch to idle status - self.status = 0; - continue - - # in idle status we search for a '#' or for a 'm' - if self.status == 0: - if c == "#": - # this could be a comment or a filename - self.status = 1; - continue - elif c == "m": - # this should be a msgid start... - s = self.f.read(4) - assert s == "sgid" - # so now we search for a '"' - self.status = 2 - continue - # in idle only those other chars are possibile - assert c in [ "\n", " ", "\t" ] - - # searching for the msgid string - if self.status == 2: - if c == "\n": - # a double LF is not possible here - c = self.f.read(1) - assert c != "\n" - if c == "\"": - # ok, this is the start of the string, - # now search for the end - while 1: - c = self.f.read(1) - if not c: - # EOF, bailout - self.status = 4 - return 0 - if c == "\\": - # a quoted char... - c = self.f.read(1) - if self.esc.has_key(c): - self.msgid += self.esc[c] - else: - self.msgid += c - continue - if c == "\"": - # end of string found - break - # a normal char, add it - self.msgid += c - if c == "m": - # this should be a msgstr identifier - s = self.f.read(5) - assert s == "sgstr" - # ok, now search for the msgstr string - self.status = 3 - - # searching for the msgstr string - if self.status == 3: - if c == "\n": - # a double LF is the end of the msgstr! - c = self.f.read(1) - if c == "\n": - # ok, time to go idle and return - self.status = 0 - self.line += 1 - return 1 - if c == "\"": - # start of string found - while 1: - c = self.f.read(1) - if not c: - # EOF, bail out - self.status = 4 - return 1 - if c == "\\": - # a quoted char... - c = self.f.read(1) - if self.esc.has_key(c): - self.msgid += self.esc[c] - else: - self.msgid += c - continue - if c == "\"": - # end of string - break - # a normal char, add it - self.msgstr += c - - - - -def check_file(translatedFile, originalFile, html=0, quiet=0): - """check a translated template against the original one - search also <MM-*> tags if html is not zero""" - - if html: - c = TransChecker("(%%|%\([^)]+\)[0-9]*[sd]|</?MM-[^>]+>)", "^%%$") - else: - c = TransChecker("(%%|%\([^)]+\)[0-9]*[sd])", "^%%$") - - try: - f = open(originalFile) - except IOError: - if not quiet: - print " - Can'open original file " + originalFile - return 1 - - while 1: - line = f.readline() - if not line: break - c.checkin(line) - - f.close() - - try: - f = open(translatedFile) - except IOError: - if not quiet: - print " - Can'open translated file " + translatedFile - return 1 - - while 1: - line = f.readline() - if not line: break - c.checkout(line) - - f.close() - - n = 0 - msg = "" - for desc in c.computeErrors(): - n +=1 - if not quiet: - print " - %(desc)s" % { 'desc': desc } - return n - - - -def check_po(file, quiet=0): - "scan the po file comparing msgids with msgstrs" - n = 0 - p = POParser(file) - c = TransChecker("(%%|%\([^)]+\)[0-9]*[sdu]|%[0-9]*[sdu])", "^%%$") - while p.parse(): - if p.msgstr: - c.reset() - c.checkin(p.msgid) - c.checkout(p.msgstr) - for desc in c.computeErrors(): - n += 1 - if not quiet: - print " - near line %(line)d %(file)s: %(desc)s" % { - 'line': p.line, - 'file': p.files, - 'desc': desc - } - p.close() - return n - - -def main(): - try: - opts, args = getopt.getopt(sys.argv[1:], 'qh', ['quiet', 'help']) - except getopt.error, msg: - usage(1, msg) - - quiet = 0 - for opt, arg in opts: - if opt in ('-h', '--help'): - usage(0) - elif opt in ('-q', '--quiet'): - quiet = 1 - - if len(args) <> 1: - usage(1) - - lang = args[0] - - isHtml = re.compile("\.html$"); - isTxt = re.compile("\.txt$"); - - numerrors = 0 - numfiles = 0 - try: - files = os.listdir("templates/" + lang + "/") - except: - print "can't open templates/%s/" % lang - for file in files: - fileEN = "templates/en/" + file - fileIT = "templates/" + lang + "/" + file - errlist = [] - if isHtml.search(file): - if not quiet: - print "HTML checking " + fileIT + "... " - n = check_file(fileIT, fileEN, html=1, quiet=quiet) - if n: - numerrors += n - numfiles += 1 - elif isTxt.search(file): - if not quiet: - print "TXT checking " + fileIT + "... " - n = check_file(fileIT, fileEN, html=0, quiet=quiet) - if n: - numerrors += n - numfiles += 1 - - else: - continue - - file = "messages/" + lang + "/LC_MESSAGES/mailman.po" - if not quiet: - print "PO checking " + file + "... " - n = check_po(file, quiet=quiet) - if n: - numerrors += n - numfiles += 1 - - if quiet: - print "%(errs)u warnings in %(files)u files" % { - 'errs': numerrors, - 'files': numfiles - } - - -if __name__ == '__main__': - main() |
