Revision: 4428
Author: btongminh
Date: 2007-10-06 18:45:08 +0000 (Sat, 06 Oct 2007)
Log Message:
-----------
Add a script to set preferences on all configured wikis concurrently.
Added Paths:
-----------
trunk/pywikipedia/maintenance/preferences.py
Added: trunk/pywikipedia/maintenance/preferences.py
===================================================================
--- trunk/pywikipedia/maintenance/preferences.py (rev 0)
+++ trunk/pywikipedia/maintenance/preferences.py 2007-10-06 18:45:08 UTC (rev 4428)
@@ -0,0 +1,185 @@
+""" This module contains a read-write class that represents the user preferences. """
+from HTMLParser import HTMLParser
+from htmlentitydefs import name2codepoint
+
+class Checkbox(object):
+ def __init__(self, value, state):
+ self.value = value
+ self.state = state
+ def set(self):
+ self.state = True
+ def unset(self):
+ self.state = False
+ def __bool__(self):
+ return self.state
+ def __str__(self):
+ return str(self.state)
+
+class Select(list):
+ def __init__(self):
+ list.__init__(self, ())
+ self.value = u''
+ def set(self, value):
+ self.value = value
+ def __bool__(self):
+ return bool(self.value)
+ def __str__(self):
+ return str(self.value)
+ def __unicode__(self):
+ return unicode(self.value)
+
+class Preferences(HTMLParser, dict):
+ def __init__(self, site = None):
+ HTMLParser.__init__(self)
+ dict.__init__(self, ())
+ self.in_form = False
+ self.select = None
+
+ if site: self.load(site)
+
+ def handle_entityref(self, name):
+ if name in name2codepoint:
+ self.handle_data(unichr(name2codepoint[name]))
+ else:
+ self.handle_data(u'&%s;' % name)
+ def handle_charref(self, name):
+ try:
+ self.handle_data(unichr(int(name)))
+ except ValueError:
+ self.handle_data(u'&#$s;' % name)
+ def handle_starttag(self, tag, attrs):
+ if tag == 'form':
+ self.in_form = ('method', 'post') in attrs
+
+ attrs = dict(attrs)
+ if tag == 'input' and self.in_form:
+ if attrs.get('type', 'text') in ('hidden', 'text'):
+ if 'value' in attrs and 'name' in attrs:
+ self[attrs['name']] = attrs['value']
+ elif attrs.get('type') == 'checkbox':
+ self[attrs['name']] = Checkbox(attrs['value'],
+ 'checked' in attrs)
+ elif attrs.get('type') == 'radio':
+ if attrs['name'] not in self:
+ self[attrs['name']] = Select()
+ self[attrs['name']].append(attrs['value'])
+ if 'checked' in attrs:
+ self[attrs['name']].set(attrs['value'])
+ if tag == 'select' and self.in_form:
+ self.select = Select()
+ self[attrs['name']] = self.select
+ if tag == 'option' and self.in_form:
+ if self.select:
+ self.select.append(attrs['value'])
+ if 'selected' in attrs:
+ self.select.set(attrs['value'])
+
+ def handle_endtag(self, tag):
+ if self.in_form and tag == 'form':
+ self.in_form = False
+ if self.select and tag == 'select':
+ self.select = None
+
+
+ def load(self, site):
+ site.forceLogin()
+ data = site.getUrl(site.path() + '?title=Special:Preferences')
+ self.feed(data)
+ self.close()
+ self.site = site
+
+ def save(self):
+ predata = {'wpSaveprefs': '1', 'title': 'Special:Preferences'}
+ for key, value in self.iteritems():
+ if value:
+ if type(value) in (Checkbox, Select):
+ predata[key] = value.value
+ else:
+ predata[key] = value
+ self.site.postForm(self.site.path(), predata)
+ def set(self, key, value):
+ if key in self:
+ if type(self[key]) is Select:
+ return self.key.set(value)
+ elif type(self[key]) is Checkbox:
+ if value:
+ return self[key].set()
+ else:
+ return self[key].unset()
+ self[key] = value
+
+
+def table_cell(value, length):
+ s = u'| ' + unicode(value)
+ tabs = length - (len(s) / 8)
+ if tabs < 0: tabs = 0
+ s = s + '\t' * tabs
+ return s
+
+def set_all(keys, values, verbose = False):
+ import wikipedia, config
+ for family in config.usernames:
+ for lang in config.usernames[family]:
+ site = wikipedia.getSite(family, lang, persistent_http = True)
+ prefs = Preferences(site)
+ for key, value in zip(keys, values):
+ prev = unicode(prefs.get(key, ''))
+ if verbose: wikipedia.output(u"Setting '%s' on %s from '%s' to '%s'." % \
+ (key, site, prev, value))
+ prefs.set(key, value)
+ prefs.save()
+ site.conn.close()
+
+def main():
+ import wikipedia, config
+
+ wikipedia.output(u'Warning! This script will set preferences on all configured accounts!')
+ wikipedia.output(u'You have %s accounts configured.' % \
+ len(map(len, filter(None, config.usernames.itervalues()))))
+
+ if wikipedia.inputChoice(u'Do you wish to continue?', ['no', 'yes'], ['n', 'y'], 'n') == 'n': return
+
+ if wikipedia.inputChoice(u'Do you already know which preference you wish to set?',
+ ['no', 'yes'], ['n', 'y'], 'y') == 'n':
+ site = wikipedia.getSite()
+ wikipedia.output(u'Getting list of available preferences from %s.' % site)
+ prefs = Preferences(site)
+
+ wikipedia.output(u'-------------------------------------------------------------------------')
+ wikipedia.output(u'| Name | Value |')
+ wikipedia.output(u'-------------------------------------------------------------------------')
+ pref_data = prefs.items()
+ pref_data.sort()
+ for key, value in pref_data:
+ wikipedia.output(table_cell(key, 4) + table_cell(value, 5) + '|')
+ wikipedia.output(u'-------------------------------------------------------------------------')
+ wikipedia.output(u'')
+ wikipedia.output(u'(For checkboxes: An empty string evaluates to False; all others to True)')
+ wikipedia.output(u'')
+
+ while True:
+ keys, values = [], []
+ while True:
+ try:
+ keys.append(wikipedia.input(u'Which preference do you wish to set?'))
+ except KeyboardInterrupt:
+ return
+ values.append(wikipedia.input(u"To what value do you wish to set '%s'?" % keys[-1]))
+ if wikipedia.inputChoice(u"Set more preferences?",
+ ['no', 'yes'], ['n', 'y'], 'n') == 'n': break
+
+ if wikipedia.inputChoice(u"Set %s?" % u', '.join((u'%s:%s' % (key, value)
+ for key, value in zip(keys, values))),
+ ['yes', 'no'], ['y', 'n'], 'n') == 'y':
+ set_all(keys, values, verbose = True)
+ wikipedia.output(u"Preferences have been set on all wikis.")
+
+if __name__ == '__main__':
+ import sys
+ sys.path.append('..')
+ import wikipedia
+ try:
+ wikipedia.handleArgs()
+ main()
+ finally:
+ wikipedia.stopme()
\ No newline at end of file