#! /usr/local/bin/python # -*- coding: utf-8 -*- # Overview # -------- # # this script will display the users not fulfilling their meeting quotas # # Run it as the web user, or the user that has access to the wiki data files. # # Highly Koumbit-specific. # # Still lacking: # # 3. finding *missing* people (ie. people that do not appear in any meeting, we need an external list, parse MembresDuComiteDeTravail?) # 4. finding people with a valid excuse (parse the "Absences" field) # 5. split report between meeting de reflexion and other involvements # 6. simply output which users are problematic # # Done: # 1. alias recognition (ie. Omar vs OmarBickell and Antoine vs TheAnarcat) # 2. typo correction (same problem as above) # # (C) Copyleft 2007, The Anarcat # Licensed under the GPLv2 or any later version import sys, operator, os os.chdir('/export/wiki/config') sys.path.insert(0, '/export/wiki/config') from MoinMoin import wikiutil from MoinMoin.Page import Page from MoinMoin.user import User from farmconfig import wikis import re import time import farmconfig from MoinMoin.request import RequestCLI # the pattern of meeting pages. the filter_pages will further reduce the list based on dates extracted from this pattern meeting_pages = re.compile('^.*/(....)-(..)-(..)$') # the pattern to detect the assistance listing, the main loop uses this to extract the actual user listings from meeting pages presences = re.compile('Pr.*sence.*$\s*((\s*\*.*\n)*)',re.MULTILINE) # alias -> realname mapping, used by sanitize_user_line to fix typos and match users with their aliases aliases = { 'antoine' : 'theanarcat', 'omar' : 'omarbickell' , 'marco' : 'marcangles', 'patrickhetu' : 'patrickhétu', 'jennigalewski' : 'jenny', 'jennygalewski' : 'jenny', 'antoinebeaupré' : 'theanarcat', 'alexis' : 'alexisboulva', 'marcel-olivierbrodeur' : 'marcelolivierbrodeur' } # take a user formatted as a single line in a bullet list and output the user only def sanitize_user_line(line): # strip starting bullet line = re.sub('\s*\*\s*','',line) # just take the first word, lowercased user = line.split(' ')[0].lower().encode('utf-8') # alias expansion if user in aliases: user = aliases[user] return user # just find the meeting pages, in the last 2 months # # XXX: this algorithm is stupid, for dates calculation, i'm tired and can't think straight tonight def filter_pages(name): matches = meeting_pages.match(name) if matches: now_year = time.localtime()[0] now_month = time.localtime()[1] meeting_year = int(matches.group(1)) meeting_month = int(matches.group(2)) lower_bound = now_month - 2 if lower_bound < 1: now_year = now_year - 1 # simple: if in feb, lower is 0, then 12, if jan, lower is -1, then 11 lower_bound = 12 + lower_bound #print "now: %d %d, meeting: %d %d, lower: %d" % ( now_year, now_month, meeting_year, meeting_month, lower_bound) if now_year == meeting_year and meeting_month >= lower_bound: return name #else: # print "not within timerange: " + name.encode('utf-8') return None # main script def main(): request = RequestCLI('wiki.koumbit.net/') # the user we masquerade as to have all the pages user = User(request,name='TheAnarcat') pagelist = request.rootpage.getPageList(user=user,filter=filter_pages) # the dictionnary mapping user -> meetings participations participation = {} # main loop: analyse each valid page for assistance for name in pagelist: body = Page(request,name).get_raw_body() #r = re.compile('Pr.*sence.*$(.*)^---',re.MULTILINE | re.DOTALL) #r = re.compile("''Pr.*sence.*''*$\s*\(\(^\s\s*\*\s*\S*$\)*\)",re.MULTILINE) matches = presences.search(body) if matches: #print "page %s conforms to pattern" % name.encode('utf-8') users = matches.group(1) if not users: print "no users found??" users = map(sanitize_user_line, users.split("\n")) #print "USERS: " + ", ".join(users).encode('utf-8') for u in users: # add the meeting to this users' list if not u in participation: participation[u] = "" participation[u] += ", " + name # final display of the user assistance for u, meeting in participation.iteritems(): print " %s:: %s" % ( u, meeting.encode('utf-8')) if __name__ == "__main__": main()