[Mailman-Users] Mailman handler to run sync_members

Mark Sapiro mark at msapiro.net
Fri Dec 5 05:47:37 CET 2014

On 12/04/2014 05:55 PM, Jon 1234 wrote:

>> The get_memb script is specific to our database, but it could basically
>> be anything, even just a straight MySQL query, that produces the desired
>> list (In our case, the logic of determining whether a record in the
>> table is that of a current member is complex and in some cases involves
>> looking at dates in other records, thus the python script).
> That sounds so similar to my situation that I'm going to push my luck, and ask if I could see an anonymised version of your get_memb script - would that be all right? Even the "who is a member?" part would be useful as, while mine would be different, it would help me with learning the necessary Python.

OK. It's attached. It is the script I run except for database names and
MySQL user and password.

It's not documented and is not straightforward for even me to follow,
and I know what it's doing.

The tPeople table contains various entries for people who may or may not
be club members. For members, there are individual and family members.
For family members there is a primary for one person and a duplicate for
the second person (all families have 2 members).

RelatedTo is the ID of the other record of a family.

Duplicate records expiration doesn't count - look up the expiration of
the RelatedTo record.

Some of the things I do are because I don't trust the integrity of the
data in the database.

Mark Sapiro <mark at msapiro.net>        The highway is for gamblers,
San Francisco Bay Area, California    better use your sense - B. Dylan
-------------- next part --------------
# Makes a list of "name" <address> for all current members email addresses.
import sys
import time
import MySQLdb
import datetime

# Is this production?
PROD = True
TYPES = ['i',
FAM_TYPES = ['f',
DUP_TYPES = ['d',

def compdate(d1, d2):
    """Compares two datetime.date instances and returns an integer
       equal to the number of months between them ignoring day of
       month. =0 if the two dates are in the same year&month, >0 if
       d2's year&month is > d1's year&month and <0 otherwise."""

    return d2.month - d1.month + 12 * (d2.year - d1.year)

def main():
    if PROD:
        base = 'xxxxxx'
        base = 'xxxxxx_sand'
    db=MySQLdb.connect(user='xxxxxx', passwd='xxxxxx', db=base)
    c = db.cursor()
    c.execute("""SELECT ID, RelatedTo, First, Last, eMail, Expiration,
                 memberno, Type FROM tPeople""")

    dic = {}
    while True:
        rec = c.fetchone()
        if not rec:
        dic[rec[0]] = rec
    dv = dic.values()
    dv.sort(lambda x, y: cmp(x[3] + x[2], y[3] + y[2]))
    emails = {}
    for rec in dv:
        id, related, first, last, e_mail, exdate, memberno, type = rec
        if not e_mail:
        if not type or not type.lower() in TYPES:
        if type.lower() in DUP_TYPES:
                if not dic[rec[1]][7] or dic[rec[1]][7].lower() not in FAM_TYPES:
                exdate = dic[rec[1]][5]
            except KeyError:
                #print >> sys.stderr, rec
        if not exdate:
            print >> sys.stderr, 'No exdate for %s %s' % (first, last)
        if compdate(datetime.date.today(), exdate) < 0:

        if e_mail in emails:
            if type.lower() in DUP_TYPES:
            elif emails[e_mail][2].lower() in DUP_TYPES:
                emails[e_mail] = (first, last, type)
                print >> sys.stderr, 'Relateds, neither is dup.\n    ',
                print >> sys.stderr, rec
            emails[e_mail] = (first, last, type)

    for e_mail, name_type in emails.items():
        print '"%s %s" <%s>' % (name_type[0], name_type[1], e_mail)

if __name__ == '__main__':

More information about the Mailman-Users mailing list