Revision: 6540
Author: nicdumz
Date: 2009-03-24 01:15:50 +0000 (Tue, 24 Mar 2009)
Log Message:
-----------
Fixing indentation: Converting tabs, removing trailing whitespaces
Modified Paths:
--------------
trunk/pywikipedia/add_text.py
trunk/pywikipedia/archivebot.py
trunk/pywikipedia/articlenos.py
trunk/pywikipedia/blockpageschecker.py
trunk/pywikipedia/casechecker.py
trunk/pywikipedia/checkimages.py
trunk/pywikipedia/commonsdelinker/checkusage.py
trunk/pywikipedia/commonsdelinker/delinker.py
trunk/pywikipedia/commonsdelinker/image_replacer.py
trunk/pywikipedia/commonsdelinker/plugins/books.py
trunk/pywikipedia/commonsdelinker/plugins/debug.py
trunk/pywikipedia/commonsdelinker/plugins/flags.py
trunk/pywikipedia/commonsdelinker/plugins/skipped_pages.py
trunk/pywikipedia/commonsdelinker/threadpool.py
trunk/pywikipedia/config.py
trunk/pywikipedia/copyright.py
trunk/pywikipedia/copyright_put.py
trunk/pywikipedia/date.py
trunk/pywikipedia/delinker.py
trunk/pywikipedia/djvutext.py
trunk/pywikipedia/families/anarchopedia_family.py
trunk/pywikipedia/families/battlestarwiki_family.py
trunk/pywikipedia/families/memoryalpha_family.py
trunk/pywikipedia/families/uncyclopedia_family.py
trunk/pywikipedia/families/wikiversity_family.py
trunk/pywikipedia/family.py
trunk/pywikipedia/followlive.py
trunk/pywikipedia/image.py
trunk/pywikipedia/imagecopy.py
trunk/pywikipedia/inline_images.py
trunk/pywikipedia/login.py
trunk/pywikipedia/logindata.py
trunk/pywikipedia/maintenance/preferences.py
trunk/pywikipedia/maintenance/setmail.py
trunk/pywikipedia/maintenance/update_namespaces.py
trunk/pywikipedia/misspelling.py
trunk/pywikipedia/mysql_autoconnection.py
trunk/pywikipedia/nowcommons.py
trunk/pywikipedia/redirect.py
trunk/pywikipedia/refcheck.py
trunk/pywikipedia/reflinks.py
trunk/pywikipedia/simple_family.py
trunk/pywikipedia/speedy_delete.py
trunk/pywikipedia/spellcheck.py
trunk/pywikipedia/standardize_notes.py
trunk/pywikipedia/template.py
trunk/pywikipedia/testfamily.py
trunk/pywikipedia/us-states.py
trunk/pywikipedia/userinterfaces/terminal_interface.py
trunk/pywikipedia/userlib.py
trunk/pywikipedia/wikipedia.py
trunk/pywikipedia/wiktionary/entry.py
trunk/pywikipedia/wiktionary/meaning.py
trunk/pywikipedia/wiktionary/wiktionarypagetest.py
trunk/pywikipedia/wiktionary.py
Modified: trunk/pywikipedia/add_text.py
===================================================================
--- trunk/pywikipedia/add_text.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/add_text.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -78,7 +78,7 @@
""" Error class for when the user doesn't specified all the data
needed """
class NothingFound(wikipedia.Error):
- """ An exception indicating that a regex has return [] instead of
results."""
+ """ An exception indicating that a regex has return [] instead of
results."""
# Useful for the untagged function
def pageText(url):
Modified: trunk/pywikipedia/archivebot.py
===================================================================
--- trunk/pywikipedia/archivebot.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/archivebot.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -56,7 +56,7 @@
'ArchiveSummary': u'Archiving %(count)d thread(s) from
[[%(from)s]].',
'OlderThanSummary': u'older than',
},
- 'ar': {
+ 'ar': {
'ArchiveFull': u'(الأرشيف ممتلئ)',
'InitialArchiveHeader': u'{{أرشيف نقاش}}',
'PageSummary': u'أرشفة %(count)d قسم(أقسام) (%(why)s) إلى
%(archives)s.',
@@ -76,7 +76,7 @@
'PageSummary': u'%(count)d szakasz archiválása (%(why)s) a(z)
%(archives)s lapra.',
'ArchiveSummary': u'%(count)d szakasz archiválása a(z)
[[%(from)s]] lapról.',
'OlderThanSummary': u'régebbi, mint',
- },
+ },
'no': {
'ArchiveFull': u'(ARKIV FULLT)',
'InitialArchiveHeader': u'{{arkiv}}',
@@ -225,7 +225,7 @@
# 18. apr 2006 kl.18:39 (UTC)
# 4. nov 2006 kl. 20:46 (CET)
if not TM:
- TM = re.search(r'(\d\d?)\. (\S+) (\d\d\d\d) kl\.\W*(\d\d):(\d\d)
\(.*?\)', line)
+ TM = re.search(r'(\d\d?)\. (\S+) (\d\d\d\d) kl\.\W*(\d\d):(\d\d)
\(.*?\)', line)
if TM:
# wikipedia.output(TM)
TIME = txt2timestamp(TM.group(0),"%d. %b %Y kl. %H:%M (%Z)")
Modified: trunk/pywikipedia/articlenos.py
===================================================================
--- trunk/pywikipedia/articlenos.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/articlenos.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -21,8 +21,8 @@
def __init__(self, site, channel, nickname, server, port=6667):
SingleServerIRCBot.__init__(self, [(server, port)], nickname, nickname)
self.channel = channel
- self.site = site
- self.other_ns = re.compile(u'14\[\[07(' + u'|'.join(site.namespaces())
+ u')')
+ self.site = site
+ self.other_ns = re.compile(u'14\[\[07(' +
u'|'.join(site.namespaces()) + u')')
self.api_url = self.site.api_address()
self.api_url +=
'action=query&meta=siteinfo&siprop=statistics&format=xml'
self.api_found = re.compile(r'articles="(.*?)"')
@@ -35,7 +35,7 @@
c.join(self.channel)
def on_privmsg(self, c, e):
- pass
+ pass
def on_pubmsg(self, c, e):
match = self.re_edit.match(e.arguments()[0])
@@ -59,19 +59,19 @@
return
except wikipedia.IsRedirectPage:
return
- print entry[0], name
+ print entry[0], name
def on_dccmsg(self, c, e):
- pass
+ pass
def on_dccchat(self, c, e):
- pass
+ pass
def do_command(self, e, cmd):
- pass
+ pass
def on_quit(self, e, cmd):
- pass
+ pass
def main():
site = wikipedia.getSite()
Modified: trunk/pywikipedia/blockpageschecker.py
===================================================================
--- trunk/pywikipedia/blockpageschecker.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/blockpageschecker.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -121,7 +121,7 @@
# Category where the bot will check
categoryToCheck = {
'en':[u'Category:Protected'],
- 'ar':[u'تصنيف:محتويات محمية'],
+ 'ar':[u'تصنيف:محتويات محمية'],
'fr':[u'Category:Page semi-protégée', u'Category:Page
protégée', u'Catégorie:Article protégé'],
'he':[u'קטגוריה:ויקיפדיה: דפים מוגנים',
u'קטגוריה:ויקיפדיה: דפים מוגנים חלקית'],
'it':[u'Categoria:Pagine semiprotette',
u'Categoria:Voci_protette'],
@@ -134,7 +134,7 @@
# Comment used when the Bot edits
comment = {
'en':u'Bot: Deleting out-dated template',
- 'ar':u'بوت: حذف قالب قديم',
+ 'ar':u'بوت: حذف قالب قديم',
'fr':u'Robot: Mise à jour des bandeaux de protection',
'he':u'בוט: מסיר תבנית שעבר זמנה',
'it':u'Bot: Tolgo o sistemo template di avviso blocco',
Modified: trunk/pywikipedia/casechecker.py
===================================================================
--- trunk/pywikipedia/casechecker.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/casechecker.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -69,7 +69,7 @@
}
msgLinkReplacement = {
'en': u'Case Replacements',
- 'ar': u'استبدالات الحالة',
+ 'ar': u'استبدالات الحالة',
'ru': u'[[ВП:КЛ]]',
}
Modified: trunk/pywikipedia/checkimages.py
===================================================================
--- trunk/pywikipedia/checkimages.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/checkimages.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -136,7 +136,7 @@
# When the Bot find that the usertalk is empty is not pretty to put only the no source
without the welcome, isn't it?
empty = {
'commons':u'{{subst:welcome}}\n~~~~\n',
- 'ar' :u'{{ترحيب}}\n~~~~\n',
+ 'ar' :u'{{ترحيب}}\n~~~~\n',
'de' :u'{{subst:willkommen}} ~~~~',
'en' :u'{{welcome}}\n~~~~\n',
'hu' :u'{{subst:Üdvözlet|~~~~}}\n',
@@ -165,7 +165,7 @@
# In reality, there aren't unknown extension, they are only not allowed...
delete_immediately = {
'commons':u"{{speedy|The file has .%s as extension. Is it ok?
Please check.}}",
- 'ar' :u"{{شطب|الملف له .%s كامتداد.}}",
+ 'ar' :u"{{شطب|الملف له .%s كامتداد.}}",
'en' :u"{{db-meta|The file has .%s as extension.}}",
'hu' :u'{{azonnali|A fájlnak .%s a kiterjesztése}}',
'it' :u'{{cancella subito|motivo=Il file ha come estensione
".%s"}}',
@@ -178,7 +178,7 @@
# The header of the Unknown extension's message.
delete_immediately_head = {
'commons':u"\n== Unknown extension! ==\n",
- 'ar' :u"\n== امتداد غير معروف! ==\n",
+ 'ar' :u"\n== امتداد غير معروف! ==\n",
'en' :u"\n== Unknown extension! ==\n",
'hu' :u'\n== Ismeretlen kiterjesztésű fájl ==\n',
'it' :u'\n\n== File non specificato ==\n',
@@ -230,7 +230,7 @@
nothing_notification = {
'commons':u"\n{{subst:User:Filnik/untagged|File:%s}}\n\n''This
message was '''added automatically by [[User:" + \
"__botnick__|__botnick__]]''', if you need some help
about it, ask its master (~~~) or go to the [[Commons:Help desk]]''.
--~~~~",
- 'ar' :u"{{subst:مصدر الصورة|File:%s}} --~~~~",
+ 'ar' :u"{{subst:مصدر الصورة|File:%s}} --~~~~",
'de' :u'\n{{subst:Benutzer:ABF/D2|%s}} ~~~~ ',
'en' :u"{{subst:image source|File:%s}} --~~~~",
'hu' :u"{{subst:adjforrást|Kép:%s}} \n Ezt az üzenetet
~~~ automatikusan helyezte el a vitalapodon, kérdéseddel fordulj a gazdájához, vagy a
[[WP:KF|Kocsmafalhoz]]. --~~~~",
@@ -295,7 +295,7 @@
# The text added in the report
report_text = {
'commons':u"\n*[[:File:%s]] " + timeselected,
- 'ar':u"\n*[[:صورة:%s]] " + timeselected,
+ 'ar':u"\n*[[:صورة:%s]] " + timeselected,
'de':u"\n*[[:Bild:%s]] " + timeselected,
'en':u"\n*[[:File:%s]] " + timeselected,
'hu':u"\n*[[:Kép:%s]] " + timeselected,
@@ -327,7 +327,7 @@
# Warning 3: the part that use this regex is case-insensitive (just to let you know..)
HiddenTemplate = {
'commons':[u'Template:Information'], # Put the other in the page
on the project defined below
- 'ar':[u'Template:معلومات'],
+ 'ar':[u'Template:معلومات'],
'de':[u'Template:Information'],
'en':[u'Template:Information'],
'hu':[u'Template:Információ', u'Template:Enwiki',
u'Template:Azonnali'],
Modified: trunk/pywikipedia/commonsdelinker/checkusage.py
===================================================================
--- trunk/pywikipedia/commonsdelinker/checkusage.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/commonsdelinker/checkusage.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -45,346 +45,346 @@
import wikipedia, family
try:
- import MySQLdb
+ import MySQLdb
except ImportError:
- pass
+ pass
try:
- import mysql_autoconnection
+ import mysql_autoconnection
except ImportError:
- pass
+ pass
__ver__ = '0.4c'
def strip_ns(title):
- title = title.replace(' ', '_')
- if title.find(':') != -1:
- return title[title.find(':') + 1:]
- return title
+ title = title.replace(' ', '_')
+ if title.find(':') != -1:
+ return title[title.find(':') + 1:]
+ return title
def strip_image(title):
- if title.startswith('Image:'):
- return strip_ns(title)
- return title
-
+ if title.startswith('Image:'):
+ return strip_ns(title)
+ return title
+
def family(domain):
- if domain is None:
- raise RuntimeError('None is not a valid family')
-
- wiki = domain.split('.')
- # Standard family
- if wiki[1] in ('wikipedia', 'wiktionary', 'wikibooks',
- 'wikiquote', 'wikisource', 'wikinews', 'wikiversity'):
- return wiki[0], wiki[1]
- # Family on own domain
- if wiki[0] == 'www':
- return wiki[1], wiki[1]
- # Special Wikimedia wiki
- if wiki[1] == 'wikimedia':
- return wiki[0], wiki[0]
- # Multilingual wikisource
- if domain == 'wikisource.org':
- return '-', 'wikisource'
- raise RuntimeError('Unknown family ' + domain)
+ if domain is None:
+ raise RuntimeError('None is not a valid family')
+
+ wiki = domain.split('.')
+ # Standard family
+ if wiki[1] in ('wikipedia', 'wiktionary', 'wikibooks',
+ 'wikiquote', 'wikisource', 'wikinews',
'wikiversity'):
+ return wiki[0], wiki[1]
+ # Family on own domain
+ if wiki[0] == 'www':
+ return wiki[1], wiki[1]
+ # Special Wikimedia wiki
+ if wiki[1] == 'wikimedia':
+ return wiki[0], wiki[0]
+ # Multilingual wikisource
+ if domain == 'wikisource.org':
+ return '-', 'wikisource'
+ raise RuntimeError('Unknown family ' + domain)
# Not sure whether this belongs here
class HTTP(object):
- def __init__(self, host):
- self.host = host
- self._conn = httplib.HTTPConnection(host)
- #self._conn.set_debuglevel(100)
- self._conn.connect()
+ def __init__(self, host):
+ self.host = host
+ self._conn = httplib.HTTPConnection(host)
+ #self._conn.set_debuglevel(100)
+ self._conn.connect()
- def request(self, method, path, headers, data):
- if not headers: headers = {}
- if not data: data = ''
- headers['Connection'] = 'Keep-Alive'
- headers['User-Agent'] = 'MwClient/' + __ver__
+ def request(self, method, path, headers, data):
+ if not headers: headers = {}
+ if not data: data = ''
+ headers['Connection'] = 'Keep-Alive'
+ headers['User-Agent'] = 'MwClient/' + __ver__
- try:
- self._conn.request(method, path, data, headers)
- except socket.error, e:
- self._conn.close()
- raise
+ try:
+ self._conn.request(method, path, data, headers)
+ except socket.error, e:
+ self._conn.close()
+ raise
- try:
- res = self._conn.getresponse()
- except httplib.BadStatusLine:
- self._conn.close()
- self._conn.connect()
- self._conn.request(method, path, data, headers)
- res = self._conn.getresponse()
+ try:
+ res = self._conn.getresponse()
+ except httplib.BadStatusLine:
+ self._conn.close()
+ self._conn.connect()
+ self._conn.request(method, path, data, headers)
+ res = self._conn.getresponse()
- if res.status >= 500:
- self._conn.request(method, path, data, headers)
- res = self._conn.getresponse()
+ if res.status >= 500:
+ self._conn.request(method, path, data, headers)
+ res = self._conn.getresponse()
- if res.status != 200:
- raise RuntimeError, (res.status, res)
+ if res.status != 200:
+ raise RuntimeError, (res.status, res)
- return res
+ return res
- def query_api(self, host, path, **kwargs):
- data = urlencode([(k, v.encode('utf-8')) for k, v in kwargs.iteritems()])
- if path.endswith('query.php'):
- query_string = '%s?format=json&%s' % (path, data)
- method = 'GET'
- data = ''
- elif path.endswith('api.php'):
- query_string = '%s?format=json' % path
- method = 'POST'
- else:
- raise ValueError('Unknown api %s' % repr(api))
+ def query_api(self, host, path, **kwargs):
+ data = urlencode([(k, v.encode('utf-8')) for k, v in
kwargs.iteritems()])
+ if path.endswith('query.php'):
+ query_string = '%s?format=json&%s' % (path, data)
+ method = 'GET'
+ data = ''
+ elif path.endswith('api.php'):
+ query_string = '%s?format=json' % path
+ method = 'POST'
+ else:
+ raise ValueError('Unknown api %s' % repr(api))
- try:
- res = self.request(method, query_string,
- {'Host': host, 'Content-Type':
'application/x-www-form-urlencoded'}, data)
- except httplib.ImproperConnectionState:
- self._conn.close()
- self.__init__(self.host)
- try:
- data = simplejson.load(res)
- finally:
- res.close()
-
- if 'error' in data:
- if data['error']['code'] ==
u'internal_api_error_DBConnectionError':
- return self.query_api(host, path, **kwargs)
- raise wikipedia.Error(data['error']['code'],
- data['error']['info'])
-
- return data
- def close(self):
- self._conn.close()
+ try:
+ res = self.request(method, query_string,
+ {'Host': host, 'Content-Type':
'application/x-www-form-urlencoded'}, data)
+ except httplib.ImproperConnectionState:
+ self._conn.close()
+ self.__init__(self.host)
+ try:
+ data = simplejson.load(res)
+ finally:
+ res.close()
+
+ if 'error' in data:
+ if data['error']['code'] ==
u'internal_api_error_DBConnectionError':
+ return self.query_api(host, path, **kwargs)
+ raise wikipedia.Error(data['error']['code'],
+ data['error']['info'])
+
+ return data
+ def close(self):
+ self._conn.close()
class HTTPPool(list):
- def __init__(self, retry_timeout = 10, max_retries = -1,
- callback = lambda *args: None):
-
- self.retry_timeout = retry_timeout
- self.max_retries = -1
- self.callback = callback
- self.current_retry = 0
-
- list.__init__(self, ())
-
- def query_api(self, host, path, **kwargs):
- conn = self.find_conn(host)
- while True:
- try:
- res = conn.query_api(host, path, **kwargs)
- self.current_retry = 0
- return res
- except RuntimeError:
- self.wait()
- except socket.error:
- conn.close()
- self.remove(conn)
- self.wait()
- conn = self.find_conn(host)
+ def __init__(self, retry_timeout = 10, max_retries = -1,
+ callback = lambda *args: None):
+
+ self.retry_timeout = retry_timeout
+ self.max_retries = -1
+ self.callback = callback
+ self.current_retry = 0
+
+ list.__init__(self, ())
+
+ def query_api(self, host, path, **kwargs):
+ conn = self.find_conn(host)
+ while True:
+ try:
+ res = conn.query_api(host, path, **kwargs)
+ self.current_retry = 0
+ return res
+ except RuntimeError:
+ self.wait()
+ except socket.error:
+ conn.close()
+ self.remove(conn)
+ self.wait()
+ conn = self.find_conn(host)
-
- def find_conn(self, host):
- for conn in self:
- if host in conn.hosts:
- return conn
- for conn in self:
- while True:
- try:
- conn.request('HEAD', '/w/api.php', {}, '').read()
- except RuntimeError, e:
- if e[0] < 500:
- break
- else:
- conn.hosts.append(host)
- return conn
- conn = HTTP(host)
- conn.hosts = []
- self.append(conn)
- return self
-
- def wait(self):
- if self.current_retry > self.max_retries and self.max_retries != -1:
- raise RuntimeError('Maximum retries exceeded')
- if self.current_retry:
- self.callback(self)
- time.sleep(self.current_retry * self.retry_timeout)
- self.current_retry += 1
-
- def close(self):
- for conn in self:
- conn.close()
- del self[:]
-
+
+ def find_conn(self, host):
+ for conn in self:
+ if host in conn.hosts:
+ return conn
+ for conn in self:
+ while True:
+ try:
+ conn.request('HEAD', '/w/api.php', {},
'').read()
+ except RuntimeError, e:
+ if e[0] < 500:
+ break
+ else:
+ conn.hosts.append(host)
+ return conn
+ conn = HTTP(host)
+ conn.hosts = []
+ self.append(conn)
+ return self
+
+ def wait(self):
+ if self.current_retry > self.max_retries and self.max_retries != -1:
+ raise RuntimeError('Maximum retries exceeded')
+ if self.current_retry:
+ self.callback(self)
+ time.sleep(self.current_retry * self.retry_timeout)
+ self.current_retry += 1
+
+ def close(self):
+ for conn in self:
+ conn.close()
+ del self[:]
+
class CheckUsage(object):
- def __init__(self, limit = 100,
- mysql_default_server = 3, mysql_host_prefix = 'sql-s', mysql_kwargs = {},
- no_db = False, use_autoconn = False,
-
- http_retry_timeout = 30, http_max_retries = -1,
- http_callback = lambda *args: None,
-
- mysql_retry_timeout = 60,
- mysql_max_retries = -1, mysql_callback = lambda *args: None):
-
- self.http = None
- self.http_retry_timeout = http_retry_timeout
- self.http_max_retries = http_max_retries
- self.http_callback = http_callback
-
- if no_db: return
+ def __init__(self, limit = 100,
+ mysql_default_server = 3, mysql_host_prefix = 'sql-s', mysql_kwargs =
{},
+ no_db = False, use_autoconn = False,
+
+ http_retry_timeout = 30, http_max_retries = -1,
+ http_callback = lambda *args: None,
+
+ mysql_retry_timeout = 60,
+ mysql_max_retries = -1, mysql_callback = lambda *args: None):
+
+ self.http = None
+ self.http_retry_timeout = http_retry_timeout
+ self.http_max_retries = http_max_retries
+ self.http_callback = http_callback
+
+ if no_db: return
- self.mysql_host_prefix = mysql_host_prefix
- self.mysql_kwargs = mysql_kwargs.copy() # To be safe
- if 'host' in self.mysql_kwargs: del self.mysql_kwargs['host']
- self.use_autoconn = use_autoconn
- self.mysql_retry_timeout = mysql_retry_timeout
- self.mysql_max_retries = mysql_max_retries
- self.mysql_callback = mysql_callback
-
- self.connections = []
-
- # Mapping database name -> mysql connection
- self.databases = {}
- # Mapping server id -> mysql connection
- self.servers = {}
- # Mapping database name -> (lang, family)
- self.sites = {}
-
- self.domains = {}
-
- self.unknown_families = []
- # Mapping family name -> family object
- self.known_families = {}
+ self.mysql_host_prefix = mysql_host_prefix
+ self.mysql_kwargs = mysql_kwargs.copy() # To be safe
+ if 'host' in self.mysql_kwargs: del self.mysql_kwargs['host']
+ self.use_autoconn = use_autoconn
+ self.mysql_retry_timeout = mysql_retry_timeout
+ self.mysql_max_retries = mysql_max_retries
+ self.mysql_callback = mysql_callback
+
+ self.connections = []
+
+ # Mapping database name -> mysql connection
+ self.databases = {}
+ # Mapping server id -> mysql connection
+ self.servers = {}
+ # Mapping database name -> (lang, family)
+ self.sites = {}
+
+ self.domains = {}
+
+ self.unknown_families = []
+ # Mapping family name -> family object
+ self.known_families = {}
- database, cursor = self.connect_mysql(mysql_host_prefix + str(mysql_default_server))
- self.servers[mysql_default_server] = (database, cursor)
+ database, cursor = self.connect_mysql(mysql_host_prefix +
str(mysql_default_server))
+ self.servers[mysql_default_server] = (database, cursor)
- # Find where the databases are located
- cursor.execute('SELECT dbname, domain, server FROM toolserver.wiki ORDER BY size
DESC LIMIT %s', (limit, ))
- for dbname, domain, server in cursor.fetchall():
- if server not in self.servers:
- self.servers[server] = self.connect_mysql(mysql_host_prefix + str(server))
-
- # FIXME: wikimediafoundation!
- # TODO: This is one big mess
- try:
- lang, fam = family(domain)
- if fam not in self.known_families:
- self.known_families[fam] = wikipedia.Family(fam, fatal = False)
- except (RuntimeError, ValueError, SyntaxError):
- self.unknown_families.append(domain)
- else:
- self.sites[dbname] = (lang, fam)
- self.databases[dbname] = self.servers[server]
-
- self.domains[dbname] = domain
+ # Find where the databases are located
+ cursor.execute('SELECT dbname, domain, server FROM toolserver.wiki ORDER BY
size DESC LIMIT %s', (limit, ))
+ for dbname, domain, server in cursor.fetchall():
+ if server not in self.servers:
+ self.servers[server] = self.connect_mysql(mysql_host_prefix +
str(server))
+
+ # FIXME: wikimediafoundation!
+ # TODO: This is one big mess
+ try:
+ lang, fam = family(domain)
+ if fam not in self.known_families:
+ self.known_families[fam] = wikipedia.Family(fam, fatal = False)
+ except (RuntimeError, ValueError, SyntaxError):
+ self.unknown_families.append(domain)
+ else:
+ self.sites[dbname] = (lang, fam)
+ self.databases[dbname] = self.servers[server]
+
+ self.domains[dbname] = domain
- def connect_mysql(self, host):
- # A bug in MySQLdb 1.2.1_p will force you to set
- # all your connections to use_unicode = False.
- # Please upgrade to MySQLdb 1.2.2 or higher.
- if self.use_autoconn:
- database = mysql_autoconnection.connect(
- use_unicode = False, host = host,
- retry_timeout = self.mysql_retry_timeout,
- max_retries = self.mysql_max_retries,
- callback = self.mysql_callback,
- **self.mysql_kwargs)
- else:
- database = MySQLdb.connect(use_unicode = False,
- host = host, **self.mysql_kwargs)
- cursor = database.cursor()
- self.connections.append((database, cursor))
- return database, cursor
- def connect_http(self):
- if not self.http:
- self.http = HTTPPool(retry_timeout = self.http_retry_timeout,
- max_retries = self.http_max_retries, callback = self.http_callback)
+ def connect_mysql(self, host):
+ # A bug in MySQLdb 1.2.1_p will force you to set
+ # all your connections to use_unicode = False.
+ # Please upgrade to MySQLdb 1.2.2 or higher.
+ if self.use_autoconn:
+ database = mysql_autoconnection.connect(
+ use_unicode = False, host = host,
+ retry_timeout = self.mysql_retry_timeout,
+ max_retries = self.mysql_max_retries,
+ callback = self.mysql_callback,
+ **self.mysql_kwargs)
+ else:
+ database = MySQLdb.connect(use_unicode = False,
+ host = host, **self.mysql_kwargs)
+ cursor = database.cursor()
+ self.connections.append((database, cursor))
+ return database, cursor
+ def connect_http(self):
+ if not self.http:
+ self.http = HTTPPool(retry_timeout = self.http_retry_timeout,
+ max_retries = self.http_max_retries, callback = self.http_callback)
- def get_usage(self, image):
- for dbname in self.databases:
- usage = self.get_usage_db(dbname, image, True)
- for link in usage:
- yield self.sites[dbname], link
+ def get_usage(self, image):
+ for dbname in self.databases:
+ usage = self.get_usage_db(dbname, image, True)
+ for link in usage:
+ yield self.sites[dbname], link
- def get_usage_db(self, dbname, image, shared = False):
- #image = strip_image(image)
- lang, family_name = self.sites[dbname]
- family = self.known_families[family_name]
-
- if family.shared_image_repository(lang) != (lang, family_name) and shared:
- left_join = 'LEFT JOIN %s.image ON (il_to = img_name) WHERE img_name IS NULL
AND' % dbname
- else:
- left_join = 'WHERE';
- query = """SELECT page_namespace, page_title FROM %s.page,
%s.imagelinks
- %s page_id = il_from AND il_to = %%s"""
- self.databases[dbname][1].execute(query % (dbname, dbname, left_join),
- (image.encode('utf-8', 'ignore'), ))
- for page_namespace, page_title in self.databases[dbname][1]:
- stripped_title = page_title.decode('utf-8', 'ignore')
- if page_namespace != 0:
- title = family.namespace(lang, page_namespace) + u':' + stripped_title
- else:
- title = stripped_title
- yield page_namespace, stripped_title, title
+ def get_usage_db(self, dbname, image, shared = False):
+ #image = strip_image(image)
+ lang, family_name = self.sites[dbname]
+ family = self.known_families[family_name]
+
+ if family.shared_image_repository(lang) != (lang, family_name) and shared:
+ left_join = 'LEFT JOIN %s.image ON (il_to = img_name) WHERE img_name IS
NULL AND' % dbname
+ else:
+ left_join = 'WHERE';
+ query = """SELECT page_namespace, page_title FROM %s.page,
%s.imagelinks
+ %s page_id = il_from AND il_to = %%s"""
+ self.databases[dbname][1].execute(query % (dbname, dbname, left_join),
+ (image.encode('utf-8', 'ignore'), ))
+ for page_namespace, page_title in self.databases[dbname][1]:
+ stripped_title = page_title.decode('utf-8', 'ignore')
+ if page_namespace != 0:
+ title = family.namespace(lang, page_namespace) + u':' +
stripped_title
+ else:
+ title = stripped_title
+ yield page_namespace, stripped_title, title
- def get_usage_live(self, site, image, shared = False):
- self.connect_http()
-
- if type(site) is str:
- hostname = site
- apipath = '/w/api.php'
- else:
- hostname = site.hostname()
- apipath = site.apipath()
-
- # FIXME: Use continue
- kwargs = {'action': 'query', 'iutitle': u'Image:' +
image,
- 'titles': u'Image:' + image, 'prop': 'info'}
- kwargs['list'] = 'imageusage'
- kwargs['iulimit'] = '500'
-
- res = self.http.query_api(hostname, apipath,
- **kwargs)
- if '-1' not in res['query']['pages'] and shared:
- return
-
- usages = res['query'].get('imageusage')
- if not usages: return
-
- # Apparently this someday changed from dict to list?
- if type(usages) is dict:
- usages = usages.values()
-
- for usage in usages:
- title = usage['title'].replace(' ', '_')
- namespace = usage['ns']
- if namespace != 0:
- stripped_title = strip_ns(title)
- else:
- stripped_title = title
- yield namespace, stripped_title, title
+ def get_usage_live(self, site, image, shared = False):
+ self.connect_http()
+
+ if type(site) is str:
+ hostname = site
+ apipath = '/w/api.php'
+ else:
+ hostname = site.hostname()
+ apipath = site.apipath()
+
+ # FIXME: Use continue
+ kwargs = {'action': 'query', 'iutitle': u'Image:'
+ image,
+ 'titles': u'Image:' + image, 'prop': 'info'}
+ kwargs['list'] = 'imageusage'
+ kwargs['iulimit'] = '500'
+
+ res = self.http.query_api(hostname, apipath,
+ **kwargs)
+ if '-1' not in res['query']['pages'] and shared:
+ return
+
+ usages = res['query'].get('imageusage')
+ if not usages: return
+
+ # Apparently this someday changed from dict to list?
+ if type(usages) is dict:
+ usages = usages.values()
+
+ for usage in usages:
+ title = usage['title'].replace(' ', '_')
+ namespace = usage['ns']
+ if namespace != 0:
+ stripped_title = strip_ns(title)
+ else:
+ stripped_title = title
+ yield namespace, stripped_title, title
-
- def exists(self, site, image):
- self.connect_http()
- # Check whether the image still is deleted on Commons.
- # BUG: This also returns true for images with a page, but
- # without the image itself. Can be fixed by querying query.php
- # instead of api.php.
- # BUG: This is ugly.
- return '-1' not in self.http.query_api(site.hostname(), site.apipath(),
- action = 'query', titles = 'Image:' +
image)['query']['pages']
-
-
- def close(self):
- if getattr(self, 'http'):
- self.http.close()
- if not hasattr(self, 'databases'): return
- for connection, cursor in self.databases.itervalues():
- try:
- connection.close()
- except:
- pass
+
+ def exists(self, site, image):
+ self.connect_http()
+ # Check whether the image still is deleted on Commons.
+ # BUG: This also returns true for images with a page, but
+ # without the image itself. Can be fixed by querying query.php
+ # instead of api.php.
+ # BUG: This is ugly.
+ return '-1' not in self.http.query_api(site.hostname(), site.apipath(),
+ action = 'query', titles = 'Image:' +
image)['query']['pages']
+
+
+ def close(self):
+ if getattr(self, 'http'):
+ self.http.close()
+ if not hasattr(self, 'databases'): return
+ for connection, cursor in self.databases.itervalues():
+ try:
+ connection.close()
+ except:
+ pass
-
\ No newline at end of file
+
\ No newline at end of file
Modified: trunk/pywikipedia/commonsdelinker/delinker.py
===================================================================
--- trunk/pywikipedia/commonsdelinker/delinker.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/commonsdelinker/delinker.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -52,884 +52,884 @@
WHITESPACE = u' \t\u200e\u200f\u202a\u202a\u202b\u202c\u202d\u202e'
def wait_callback(object):
- output(u'%s Connection has been lost in %s. Attempting reconnection.' %
(threading.currentThread(), repr(object)), False)
- if hasattr(object, 'error'):
- output(u'Error was %s: %s' % tuple(object.error))
-
+ output(u'%s Connection has been lost in %s. Attempting reconnection.' %
(threading.currentThread(), repr(object)), False)
+ if hasattr(object, 'error'):
+ output(u'Error was %s: %s' % tuple(object.error))
+
def universal_unicode(s):
- if type(s) is str:
- return s.decode('utf-8', 'ignore')
- return unicode(s)
+ if type(s) is str:
+ return s.decode('utf-8', 'ignore')
+ return unicode(s)
def connect_database():
- engine = config.CommonsDelinker['sql_engine']
- kwargs = config.CommonsDelinker['sql_config'].copy()
- if engine == 'mysql':
- import mysql_autoconnection
- # This setting is required for MySQL
- kwargs['charset'] = 'utf8'
- # Work around for a bug in MySQLdb 1.2.1_p. This version will
- # set use_unicode for all connections to the value of the first
- # initialized connection. This bug is not relevant for MySQLdb
- # versions 1.2.2 and upwards. The connection character set must
- # be set to utf8 however, to prevent INSERTs to be converted to
- # the standard MySQL character set.
- kwargs['use_unicode'] = False
- kwargs['callback'] = wait_callback
-
- return mysql_autoconnection.connect(**kwargs)
- # TODO: Add support for sqlite3
- raise RuntimeError('Unsupported database engine %s' % engine)
-
+ engine = config.CommonsDelinker['sql_engine']
+ kwargs = config.CommonsDelinker['sql_config'].copy()
+ if engine == 'mysql':
+ import mysql_autoconnection
+ # This setting is required for MySQL
+ kwargs['charset'] = 'utf8'
+ # Work around for a bug in MySQLdb 1.2.1_p. This version will
+ # set use_unicode for all connections to the value of the first
+ # initialized connection. This bug is not relevant for MySQLdb
+ # versions 1.2.2 and upwards. The connection character set must
+ # be set to utf8 however, to prevent INSERTs to be converted to
+ # the standard MySQL character set.
+ kwargs['use_unicode'] = False
+ kwargs['callback'] = wait_callback
+
+ return mysql_autoconnection.connect(**kwargs)
+ # TODO: Add support for sqlite3
+ raise RuntimeError('Unsupported database engine %s' % engine)
+
class ImmutableByReference(object):
- def __init__(self, data):
- self.data = data
- def set(self, value):
- self.data = value
- def get(self):
- return self.data
- def __str__(self):
- return str(self.data)
- def __unicode__(self):
- return unicode(self.data)
- def __int__(self):
- return int(self.data)
+ def __init__(self, data):
+ self.data = data
+ def set(self, value):
+ self.data = value
+ def get(self):
+ return self.data
+ def __str__(self):
+ return str(self.data)
+ def __unicode__(self):
+ return unicode(self.data)
+ def __int__(self):
+ return int(self.data)
class Delinker(threadpool.Thread):
- # TODO: Method names could use some clean up
- def __init__(self, pool, CommonsDelinker):
- threadpool.Thread.__init__(self, pool)
- self.CommonsDelinker = CommonsDelinker
- self.sql_layout = self.CommonsDelinker.config.get('sql_layout', 'new')
-
- def delink_image(self, image, usage, timestamp, admin, reason, replacement = None):
- """ Performs the delink for image on usage. """
- output(u'%s Usage of %s: %s' % (self, image, usage))
- if self.CommonsDelinker.exec_hook('before_delink',
- (image, usage, timestamp, admin, reason, replacement)) is False:
- return
-
- skipped_images = {}
- for (lang, family), pages in usage.iteritems():
- site = self.CommonsDelinker.get_site(lang, family)
- if not site:
- output(u'%s Warning! Unknown site %s:%s' % (self, family, lang))
- continue
-
- try:
- summary = self.get_summary(site, image, admin, reason, replacement)
-
- for page_namespace, page_title, title in pages:
- if (site.lang, site.family.name) == (self.CommonsDelinker.site.lang,
- self.CommonsDelinker.site.family.name) and \
- (page_namespace, page_title) == (6, image):
- continue
-
- if self.CommonsDelinker.set_edit(str(site), title):
- # The page is currently being editted. Postpone.
- if (lang, family) not in skipped_images:
- skipped_images[(lang, family)] = []
- skipped_images[(lang, family)].append(
- (page_namespace, page_title, title))
- else:
- # Delink the image
- output(u'%s Delinking %s from %s' % (self, image, site))
-
- try:
- try:
- result = self.replace_image(image, site, title, summary, replacement)
- except wikipedia.UserBlocked, e:
- output(u'Warning! Blocked %s.' % tuple(e))
- except wikipedia.CaptchaError, e:
- output(u'%s Warning! Captcha encountered at %s.' % (self, site))
- if (lang, family) not in skipped_images:
- skipped_images[(lang, family)] = []
- skipped_images[(lang, family)].append(
- (page_namespace, page_title, title))
- finally:
- self.CommonsDelinker.unset_edit(str(site), title)
-
- # Add to logging queue
- if self.sql_layout == 'new':
- self.CommonsDelinker.Loggers.append((timestamp, image,
- site.lang, site.family.name, page_namespace, page_title,
- result, replacement))
- else:
- self.CommonsDelinker.Loggers.append((timestamp, image, site.hostname(),
- page_namespace, page_title, result, replacement))
- finally:
- self.CommonsDelinker.unlock_site(site)
+ # TODO: Method names could use some clean up
+ def __init__(self, pool, CommonsDelinker):
+ threadpool.Thread.__init__(self, pool)
+ self.CommonsDelinker = CommonsDelinker
+ self.sql_layout = self.CommonsDelinker.config.get('sql_layout',
'new')
+
+ def delink_image(self, image, usage, timestamp, admin, reason, replacement = None):
+ """ Performs the delink for image on usage. """
+ output(u'%s Usage of %s: %s' % (self, image, usage))
+ if self.CommonsDelinker.exec_hook('before_delink',
+ (image, usage, timestamp, admin, reason, replacement)) is False:
+ return
+
+ skipped_images = {}
+ for (lang, family), pages in usage.iteritems():
+ site = self.CommonsDelinker.get_site(lang, family)
+ if not site:
+ output(u'%s Warning! Unknown site %s:%s' % (self, family, lang))
+ continue
+
+ try:
+ summary = self.get_summary(site, image, admin, reason, replacement)
+
+ for page_namespace, page_title, title in pages:
+ if (site.lang, site.family.name) == (self.CommonsDelinker.site.lang,
+ self.CommonsDelinker.site.family.name) and \
+ (page_namespace, page_title) == (6, image):
+ continue
+
+ if self.CommonsDelinker.set_edit(str(site), title):
+ # The page is currently being editted. Postpone.
+ if (lang, family) not in skipped_images:
+ skipped_images[(lang, family)] = []
+ skipped_images[(lang, family)].append(
+ (page_namespace, page_title, title))
+ else:
+ # Delink the image
+ output(u'%s Delinking %s from %s' % (self, image, site))
+
+ try:
+ try:
+ result = self.replace_image(image, site, title, summary,
replacement)
+ except wikipedia.UserBlocked, e:
+ output(u'Warning! Blocked %s.' % tuple(e))
+ except wikipedia.CaptchaError, e:
+ output(u'%s Warning! Captcha encountered at %s.'
% (self, site))
+ if (lang, family) not in skipped_images:
+ skipped_images[(lang, family)] = []
+ skipped_images[(lang, family)].append(
+ (page_namespace, page_title, title))
+ finally:
+ self.CommonsDelinker.unset_edit(str(site), title)
+
+ # Add to logging queue
+ if self.sql_layout == 'new':
+ self.CommonsDelinker.Loggers.append((timestamp, image,
+ site.lang, site.family.name, page_namespace, page_title,
+ result, replacement))
+ else:
+ self.CommonsDelinker.Loggers.append((timestamp, image,
site.hostname(),
+ page_namespace, page_title, result, replacement))
+ finally:
+ self.CommonsDelinker.unlock_site(site)
- self.CommonsDelinker.exec_hook('after_delink', (image, usage, timestamp, admin,
reason, replacement))
+ self.CommonsDelinker.exec_hook('after_delink', (image, usage, timestamp,
admin, reason, replacement))
- if skipped_images:
- time.sleep(self.CommonsDelinker.config['timeout'])
- output(u'Delinking from previously skipped page for %s.' % image)
- return self.delink_image(image, skipped_images, timestamp, admin, reason,
replacement)
- elif replacement:
- # Let them know that we are done replacing.
- self.CommonsDelinker.Loggers.append((timestamp, image, replacement))
-
- def replace_image(self, image, site, page_title, summary, replacement = None):
- """ The actual replacement. Giving None as argument for replacement
- will delink instead of replace."""
-
- page = wikipedia.Page(site, page_title)
- hook = None
-
- # TODO: Per site config.
- if page.namespace() in self.CommonsDelinker.config['delink_namespaces']:
- try:
- text = page.get(get_redirect = True)
- except wikipedia.NoPage:
- return 'failed'
- new_text = text
-
- m_image = ImmutableByReference(image)
- m_replacement = ImmutableByReference(replacement)
- self.CommonsDelinker.exec_hook('before_replace',
- (page, summary, m_image, m_replacement))
- image = m_image.get()
- replacement = m_replacement.get()
-
- def create_regex(s):
- first, other = re.escape(s[0]), re.escape(s[1:])
- return ur'(?:[%s%s]%s)' % (first.upper(), first.lower(), other)
- def create_regex_i(s):
- return ur'(?:%s)' % u''.join([u'[%s%s]' % (c.upper(),
c.lower()) for c in s])
-
- namespaces = site.namespace(6, all = True) + site.namespace(-2, all = True)
- r_namespace = ur'\s*(?:%s)\s*\:\s*' % u'|'.join(map(create_regex_i,
namespaces))
- # Note that this regex creates a group!
- r_image = u'(%s)' % create_regex(image).replace(r'\_', '[
_]')
-
- def simple_replacer(match):
- m_replacement = ImmutableByReference(replacement)
- groups = list(match.groups())
- if hook:
- if False is self.CommonsDelinker.exec_hook('%s_replace' % hook,
- (page, summary, image, m_replacement, match, groups)):
- return u''.join(groups)
-
- if m_replacement.get() is None:
- return u''
- else:
- groups[1] = m_replacement.get()
- return u''.join(groups)
-
- # Previously links in image descriptions will cause
- # unexpected behaviour: [[Image:image.jpg|thumb|[[link]] in description]]
- # will truncate at the first occurence of ]]. This cannot be
- # fixed using one regular expression.
- # This means that all ]] after the start of the image
- # must be located. If it then does not have an associated
- # [[, this one is the closure of the image.
-
- r_simple_s = u'(\[\[%s)%s' % (r_namespace, r_image)
- r_s = '\[\['
- r_e = '\]\]'
- # First determine where wikilinks start and end
- image_starts = [match.start() for match in re.finditer(r_simple_s, text)]
- link_starts = [match.start() for match in re.finditer(r_s, text)]
- link_ends = [match.end() for match in re.finditer(r_e, text)]
-
- r_simple = u'(\[\[%s)%s(.*)' % (r_namespace, r_image)
- hook = 'simple'
- replacements = []
- for image_start in image_starts:
- current_link_starts = [link_start for link_start in link_starts
- if link_start > image_start]
- current_link_ends = [link_end for link_end in link_ends
- if link_end > image_start]
- end = image_start
- if current_link_ends: end = current_link_ends[0]
-
- while current_link_starts and current_link_ends:
- start = current_link_starts.pop(0)
- end = current_link_ends.pop(0)
- if end <= start and end > image_start:
- # Found the end of the image
- break
-
- # Check whether this image is the first one on the line
- if image_start == 0:
- prev = ''
- else:
- prev = new_text[image_start - 1]
- if prev in ('', '\r', '\n') and replacement is None:
- # Kill all spaces after end
- while (end + 1) < len(new_text):
- if new_text[end + 1] in WHITESPACE:
- end += 1
- else:
- break
-
- # Add the replacement to the todo list. Doing the
- # replacement right know would alter the indices.
- replacements.append((new_text[image_start:end],
- re.sub(r_simple, simple_replacer,
- new_text[image_start:end])))
-
- # Perform the replacements
- for old, new in replacements:
- if old: new_text = new_text.replace(old, new)
-
- # Remove the image from galleries
- hook = 'gallery'
- r_galleries = ur'(?s)(\<%s\>)(.*?)(\<\/%s\>)' %
(create_regex_i('gallery'),
- create_regex_i('gallery'))
- r_gallery = ur'(?m)^((?:%s)?)%s(\s*(?:\|.*?)?\s*$)' % (r_namespace, r_image)
- def gallery_replacer(match):
- return ur'%s%s%s' % (match.group(1), re.sub(r_gallery,
- simple_replacer, match.group(2)), match.group(3))
- new_text = re.sub(r_galleries, gallery_replacer, new_text)
-
- if text == new_text or self.CommonsDelinker.config.get('force_complex',
False):
- # All previous steps did not work, so the image is
- # likely embedded in a complicated template.
- hook = 'complex'
- r_templates = ur'(?s)(\{\{.*?\}\})'
- r_complicated = u'(?s)(?<=[|{=])\s*((?:%s)?)%s' % (r_namespace, r_image)
-
- def template_replacer(match):
- return re.sub(r_complicated, simple_replacer, match.group(1))
- new_text = re.sub(r_templates, template_replacer, text)
-
- if text != new_text:
- # Save to the wiki
- # Code for checking user page existance has been moved
- # to summary() code, to avoid checking the user page
- # for each removal.
- new_text = ImmutableByReference(new_text)
- m_summary = ImmutableByReference(summary)
- if False is self.CommonsDelinker.exec_hook('before_save',
- (page, text, new_text, m_summary)):
- return 'skipped'
-
- is_retry = False
- while True:
- try:
- if self.CommonsDelinker.config.get('edit', True) and not \
- ((self.CommonsDelinker.site.lang == 'commons') ^ \
- (config.usernames.get('commons', {}).get(
- 'commons') == 'CommonsDelinker')):
- page.put(new_text.get(), m_summary.get())
- return 'ok'
- except wikipedia.ServerError, e:
- output(u'Warning! ServerError: %s' % str(e))
- except wikipedia.EditConflict:
- # Try again
- output(u'Got EditConflict trying to remove %s from %s:%s.' % \
- (image, site, page_title))
- return self.replace_image(image, site, page_title, summary, replacement = None)
- except wikipedia.PageNotSaved:
- if is_retry: return 'failed'
- is_retry = True
- except wikipedia.LockedPage:
- return 'failed'
- output(u'Retrying...')
- else:
- return 'skipped'
- return 'skipped'
-
-
-
- def do(self, args):
- try:
- self.delink_image(*args)
- except:
- output(u'An exception occured in %s' % self, False)
- traceback.print_exc(file = sys.stderr)
-
- def get_summary(self, site, image, admin, reason, replacement):
- """ Get the summary template and substitute the
- correct values."""
- # FIXME: Don't insert commons: on local delink
- # FIXME: Hardcode is EVIL
- if replacement:
- tlp = self.CommonsDelinker.SummaryCache.get(site, 'replace-I18n')
- else:
- tlp = self.CommonsDelinker.SummaryCache.get(site, 'summary-I18n')
-
- tlp = tlp.replace('$1', image)
- if replacement:
- tlp = tlp.replace('$2', replacement)
- tlp = tlp.replace('$3', unicode(admin))
- tlp = tlp.replace('$4', unicode(reason).replace('[[',
'[[commons:'))
- else:
- tlp = tlp.replace('$2', unicode(admin))
- tlp = tlp.replace('$3', reason.replace('[[', '[[commons:'))
-
- return tlp
-
+ if skipped_images:
+ time.sleep(self.CommonsDelinker.config['timeout'])
+ output(u'Delinking from previously skipped page for %s.' % image)
+ return self.delink_image(image, skipped_images, timestamp, admin, reason,
replacement)
+ elif replacement:
+ # Let them know that we are done replacing.
+ self.CommonsDelinker.Loggers.append((timestamp, image, replacement))
+
+ def replace_image(self, image, site, page_title, summary, replacement = None):
+ """ The actual replacement. Giving None as argument for
replacement
+ will delink instead of replace."""
+
+ page = wikipedia.Page(site, page_title)
+ hook = None
+
+ # TODO: Per site config.
+ if page.namespace() in self.CommonsDelinker.config['delink_namespaces']:
+ try:
+ text = page.get(get_redirect = True)
+ except wikipedia.NoPage:
+ return 'failed'
+ new_text = text
+
+ m_image = ImmutableByReference(image)
+ m_replacement = ImmutableByReference(replacement)
+ self.CommonsDelinker.exec_hook('before_replace',
+ (page, summary, m_image, m_replacement))
+ image = m_image.get()
+ replacement = m_replacement.get()
+
+ def create_regex(s):
+ first, other = re.escape(s[0]), re.escape(s[1:])
+ return ur'(?:[%s%s]%s)' % (first.upper(), first.lower(), other)
+ def create_regex_i(s):
+ return ur'(?:%s)' % u''.join([u'[%s%s]' %
(c.upper(), c.lower()) for c in s])
+
+ namespaces = site.namespace(6, all = True) + site.namespace(-2, all = True)
+ r_namespace = ur'\s*(?:%s)\s*\:\s*' %
u'|'.join(map(create_regex_i, namespaces))
+ # Note that this regex creates a group!
+ r_image = u'(%s)' % create_regex(image).replace(r'\_', '[
_]')
+
+ def simple_replacer(match):
+ m_replacement = ImmutableByReference(replacement)
+ groups = list(match.groups())
+ if hook:
+ if False is self.CommonsDelinker.exec_hook('%s_replace' %
hook,
+ (page, summary, image, m_replacement, match, groups)):
+ return u''.join(groups)
+
+ if m_replacement.get() is None:
+ return u''
+ else:
+ groups[1] = m_replacement.get()
+ return u''.join(groups)
+
+ # Previously links in image descriptions will cause
+ # unexpected behaviour: [[Image:image.jpg|thumb|[[link]] in description]]
+ # will truncate at the first occurence of ]]. This cannot be
+ # fixed using one regular expression.
+ # This means that all ]] after the start of the image
+ # must be located. If it then does not have an associated
+ # [[, this one is the closure of the image.
+
+ r_simple_s = u'(\[\[%s)%s' % (r_namespace, r_image)
+ r_s = '\[\['
+ r_e = '\]\]'
+ # First determine where wikilinks start and end
+ image_starts = [match.start() for match in re.finditer(r_simple_s, text)]
+ link_starts = [match.start() for match in re.finditer(r_s, text)]
+ link_ends = [match.end() for match in re.finditer(r_e, text)]
+
+ r_simple = u'(\[\[%s)%s(.*)' % (r_namespace, r_image)
+ hook = 'simple'
+ replacements = []
+ for image_start in image_starts:
+ current_link_starts = [link_start for link_start in link_starts
+ if link_start > image_start]
+ current_link_ends = [link_end for link_end in link_ends
+ if link_end > image_start]
+ end = image_start
+ if current_link_ends: end = current_link_ends[0]
+
+ while current_link_starts and current_link_ends:
+ start = current_link_starts.pop(0)
+ end = current_link_ends.pop(0)
+ if end <= start and end > image_start:
+ # Found the end of the image
+ break
+
+ # Check whether this image is the first one on the line
+ if image_start == 0:
+ prev = ''
+ else:
+ prev = new_text[image_start - 1]
+ if prev in ('', '\r', '\n') and replacement is
None:
+ # Kill all spaces after end
+ while (end + 1) < len(new_text):
+ if new_text[end + 1] in WHITESPACE:
+ end += 1
+ else:
+ break
+
+ # Add the replacement to the todo list. Doing the
+ # replacement right know would alter the indices.
+ replacements.append((new_text[image_start:end],
+ re.sub(r_simple, simple_replacer,
+ new_text[image_start:end])))
+
+ # Perform the replacements
+ for old, new in replacements:
+ if old: new_text = new_text.replace(old, new)
+
+ # Remove the image from galleries
+ hook = 'gallery'
+ r_galleries = ur'(?s)(\<%s\>)(.*?)(\<\/%s\>)' %
(create_regex_i('gallery'),
+ create_regex_i('gallery'))
+ r_gallery = ur'(?m)^((?:%s)?)%s(\s*(?:\|.*?)?\s*$)' % (r_namespace,
r_image)
+ def gallery_replacer(match):
+ return ur'%s%s%s' % (match.group(1), re.sub(r_gallery,
+ simple_replacer, match.group(2)), match.group(3))
+ new_text = re.sub(r_galleries, gallery_replacer, new_text)
+
+ if text == new_text or
self.CommonsDelinker.config.get('force_complex', False):
+ # All previous steps did not work, so the image is
+ # likely embedded in a complicated template.
+ hook = 'complex'
+ r_templates = ur'(?s)(\{\{.*?\}\})'
+ r_complicated = u'(?s)(?<=[|{=])\s*((?:%s)?)%s' %
(r_namespace, r_image)
+
+ def template_replacer(match):
+ return re.sub(r_complicated, simple_replacer, match.group(1))
+ new_text = re.sub(r_templates, template_replacer, text)
+
+ if text != new_text:
+ # Save to the wiki
+ # Code for checking user page existance has been moved
+ # to summary() code, to avoid checking the user page
+ # for each removal.
+ new_text = ImmutableByReference(new_text)
+ m_summary = ImmutableByReference(summary)
+ if False is self.CommonsDelinker.exec_hook('before_save',
+ (page, text, new_text, m_summary)):
+ return 'skipped'
+
+ is_retry = False
+ while True:
+ try:
+ if self.CommonsDelinker.config.get('edit', True) and not
\
+ ((self.CommonsDelinker.site.lang == 'commons') ^
\
+ (config.usernames.get('commons', {}).get(
+ 'commons') == 'CommonsDelinker')):
+ page.put(new_text.get(), m_summary.get())
+ return 'ok'
+ except wikipedia.ServerError, e:
+ output(u'Warning! ServerError: %s' % str(e))
+ except wikipedia.EditConflict:
+ # Try again
+ output(u'Got EditConflict trying to remove %s from
%s:%s.' % \
+ (image, site, page_title))
+ return self.replace_image(image, site, page_title, summary,
replacement = None)
+ except wikipedia.PageNotSaved:
+ if is_retry: return 'failed'
+ is_retry = True
+ except wikipedia.LockedPage:
+ return 'failed'
+ output(u'Retrying...')
+ else:
+ return 'skipped'
+ return 'skipped'
+
+
+
+ def do(self, args):
+ try:
+ self.delink_image(*args)
+ except:
+ output(u'An exception occured in %s' % self, False)
+ traceback.print_exc(file = sys.stderr)
+
+ def get_summary(self, site, image, admin, reason, replacement):
+ """ Get the summary template and substitute the
+ correct values."""
+ # FIXME: Don't insert commons: on local delink
+ # FIXME: Hardcode is EVIL
+ if replacement:
+ tlp = self.CommonsDelinker.SummaryCache.get(site, 'replace-I18n')
+ else:
+ tlp = self.CommonsDelinker.SummaryCache.get(site, 'summary-I18n')
+
+ tlp = tlp.replace('$1', image)
+ if replacement:
+ tlp = tlp.replace('$2', replacement)
+ tlp = tlp.replace('$3', unicode(admin))
+ tlp = tlp.replace('$4', unicode(reason).replace('[[',
'[[commons:'))
+ else:
+ tlp = tlp.replace('$2', unicode(admin))
+ tlp = tlp.replace('$3', reason.replace('[[',
'[[commons:'))
+
+ return tlp
+
class SummaryCache(object):
- """ Object to thread-safe cache summary templates. """
- def __init__(self, CommonsDelinker):
- self.summaries = {}
- self.lock = threading.Lock()
- self.CommonsDelinker = CommonsDelinker
-
- def get(self, site, type, key = None, default = None):
- # This can probably also provide something for
- # localised settings, but then it first needs to
- # check whether the page is sysop only.
- if not key:
- key = str(site)
-
- self.lock.acquire()
- try:
- if type not in self.summaries:
- self.summaries[type] = {}
- if key in self.summaries[type]:
- if (time.time() - self.summaries[type][key][1]) < \
- self.CommonsDelinker.config['summary_cache']:
- # Return cached result
- return self.summaries[type][key][0]
-
- output(u'%s Fetching new summary for %s' % (self, site))
-
- # FIXME: evil
- if self.CommonsDelinker.config['global']:
- self.check_user_page(site)
- page = wikipedia.Page(site, '%s%s' % \
- (self.CommonsDelinker.config['local_settings'], type))
- try:
- # Fetch the summary template, follow redirects
- i18n = page.get(get_redirect = True)
- self.summaries[type][key] = (i18n, time.time())
- return i18n
- except wikipedia.NoPage:
- pass
- finally:
- self.lock.release()
-
- # No i18n available, but it may be available in the wikipedia
- # of that language. Only do so for wiktionary, wikibooks,
- # wikiquote, wikisource, wikinews, wikiversity
- # This will cause the bot to function even on special wikis
- # like
mediawiki.org and meta and species.
- output(u'%s Using default summary for %s' % (self, site))
-
- if default: return default
-
- if site.family.name != 'wikipedia' and
self.CommonsDelinker.config['global']:
- if site.family.name in ('wiktionary', 'wikibooks',
'wikiquote',
- 'wikisource', 'wikinews', 'wikiversity'):
- if site.lang in config.usernames['wikipedia']:
- newsite = self.CommonsDelinker.get_site(site.lang,
- wikipedia.Family('wikipedia'))
- return self.get(newsite, type, key = key)
- return self.CommonsDelinker.config['default_settings'].get(type, '')
-
- def check_user_page(self, site):
- "Check whether a userpage exists. Only used for CommonsDelinker."
- try:
- # Make sure the userpage is not empty
- # Note: if wikis delete the userpage, it's there own fault
- filename = 'canedit.cdl'
- try:
- f = open(filename, 'r')
- except IOError:
- # Don't care
- return
- ftxt = f.read()
- f.close()
- if not '#' + str(site) in ftxt:
- username = config.usernames[site.family.name][site.lang]
-
- userpage = wikipedia.Page(site, 'User:' + username)
- # Removed check for page existence. If it is not in our
- # database we can safely assume that we have no user page
- # there. In case there is, we will just overwrite it once.
- # It causes no real problems, but it is one call to the
- # servers less.
- # TODO: Config setting?
- userpage.put('#REDIRECT [[m:User:CommonsDelinker]]', '')
-
- f = open(filename, 'a')
- f.write('#' + str(site))
- f.close()
- except wikipedia.LockedPage:
- # User page is protected, continue anyway
- pass
-
+ """ Object to thread-safe cache summary templates. """
+ def __init__(self, CommonsDelinker):
+ self.summaries = {}
+ self.lock = threading.Lock()
+ self.CommonsDelinker = CommonsDelinker
+
+ def get(self, site, type, key = None, default = None):
+ # This can probably also provide something for
+ # localised settings, but then it first needs to
+ # check whether the page is sysop only.
+ if not key:
+ key = str(site)
+
+ self.lock.acquire()
+ try:
+ if type not in self.summaries:
+ self.summaries[type] = {}
+ if key in self.summaries[type]:
+ if (time.time() - self.summaries[type][key][1]) < \
+ self.CommonsDelinker.config['summary_cache']:
+ # Return cached result
+ return self.summaries[type][key][0]
+
+ output(u'%s Fetching new summary for %s' % (self, site))
+
+ # FIXME: evil
+ if self.CommonsDelinker.config['global']:
+ self.check_user_page(site)
+ page = wikipedia.Page(site, '%s%s' % \
+ (self.CommonsDelinker.config['local_settings'], type))
+ try:
+ # Fetch the summary template, follow redirects
+ i18n = page.get(get_redirect = True)
+ self.summaries[type][key] = (i18n, time.time())
+ return i18n
+ except wikipedia.NoPage:
+ pass
+ finally:
+ self.lock.release()
+
+ # No i18n available, but it may be available in the wikipedia
+ # of that language. Only do so for wiktionary, wikibooks,
+ # wikiquote, wikisource, wikinews, wikiversity
+ # This will cause the bot to function even on special wikis
+ # like
mediawiki.org and meta and species.
+ output(u'%s Using default summary for %s' % (self, site))
+
+ if default: return default
+
+ if site.family.name != 'wikipedia' and
self.CommonsDelinker.config['global']:
+ if site.family.name in ('wiktionary', 'wikibooks',
'wikiquote',
+ 'wikisource', 'wikinews', 'wikiversity'):
+ if site.lang in config.usernames['wikipedia']:
+ newsite = self.CommonsDelinker.get_site(site.lang,
+ wikipedia.Family('wikipedia'))
+ return self.get(newsite, type, key = key)
+ return self.CommonsDelinker.config['default_settings'].get(type,
'')
+
+ def check_user_page(self, site):
+ "Check whether a userpage exists. Only used for CommonsDelinker."
+ try:
+ # Make sure the userpage is not empty
+ # Note: if wikis delete the userpage, it's there own fault
+ filename = 'canedit.cdl'
+ try:
+ f = open(filename, 'r')
+ except IOError:
+ # Don't care
+ return
+ ftxt = f.read()
+ f.close()
+ if not '#' + str(site) in ftxt:
+ username = config.usernames[site.family.name][site.lang]
+
+ userpage = wikipedia.Page(site, 'User:' + username)
+ # Removed check for page existence. If it is not in our
+ # database we can safely assume that we have no user page
+ # there. In case there is, we will just overwrite it once.
+ # It causes no real problems, but it is one call to the
+ # servers less.
+ # TODO: Config setting?
+ userpage.put('#REDIRECT [[m:User:CommonsDelinker]]', '')
+
+ f = open(filename, 'a')
+ f.write('#' + str(site))
+ f.close()
+ except wikipedia.LockedPage:
+ # User page is protected, continue anyway
+ pass
+
class CheckUsage(threadpool.Thread):
- timeout = 120
- def __init__(self, pool, CommonsDelinker):
- threadpool.Thread.__init__(self, pool)
- self.CommonsDelinker = CommonsDelinker
- # Not really thread safe, but we should only do read operations...
- self.site = CommonsDelinker.site
-
- def run(self):
- try:
- self.connect()
- except:
- return self.exit()
- threadpool.Thread.run(self)
-
- def connect(self):
- output(u'%s Connecting to databases' % self)
- config = self.CommonsDelinker.config
- if config['global']:
- # Note: global use requires MySQL
- self.CheckUsage = checkusage.CheckUsage(limit = sys.maxint,
- mysql_kwargs = config['sql_config'],
- use_autoconn = True,
- http_callback = wait_callback,
- mysql_callback = wait_callback)
- else:
- self.CheckUsage = checkusage.CheckUsage(sys.maxint,
- http_callback = wait_callback, no_db = True)
-
-
- def check_usage(self, image, timestamp, admin, reason, replacement):
- """ Check whether this image needs to be delinked. """
-
- # Check whether the image still is deleted on Commons.
- # BUG: This also returns true for images with a page, but
- # without the image itself. Can be fixed by querying query.php
- # instead of api.php. Also should this be made as an exits()
- # method of checkusage.CheckUsage?
- if self.site.shared_image_repository() != (None, None):
- shared_image_repository =
self.CommonsDelinker.get_site(*self.site.shared_image_repository())
- try:
- if self.CheckUsage.exists(shared_image_repository, image) \
- and not bool(replacement):
- output(u'%s %s exists on the shared image repository!' % (self, image))
- return
- finally:
- self.CommonsDelinker.unlock_site(shared_image_repository)
- if self.CheckUsage.exists(self.site, image) and \
- not bool(replacement):
- output(u'%s %s exists again!' % (self, image))
- return
-
-
- if self.CommonsDelinker.config['global']:
- usage = self.CheckUsage.get_usage(image)
- usage_domains = {}
-
- count = 0
- # Sort usage per domain
- for (lang, family), (page_namespace, page_title, title) in usage:
- if (lang, family) not in usage_domains:
- usage_domains[(lang, family)] = []
- usage_domains[(lang, family)].append((page_namespace, page_title, title))
- count += 1
- else:
- #FIX!
- usage_domains = {(self.site.lang, self.site.family.name):
- list(self.CheckUsage.get_usage_live(self.site,
- image))}
- count = len(usage_domains[(self.site.lang, self.site.family.name)])
-
- output(u'%s %s used on %s pages' % (self, image, count))
-
- if count:
- # Pass the usage to the Delinker pool along with other arguments
- self.CommonsDelinker.Delinkers.append((image, usage_domains,
- timestamp, admin, reason, replacement))
- elif replacement:
- # Record replacement done
- self.CommonsDelinker.Loggers.append((timestamp, image, replacement))
-
- def do(self, args):
- try:
- self.check_usage(*args)
- except:
- # Something unexpected happened. Report and die.
- output('An exception occured in %s' % self, False)
- traceback.print_exc(file = sys.stderr)
- self.exit()
- self.CommonsDelinker.thread_died()
-
- def starve(self):
- self.pool.jobLock.acquire()
- try:
- if self.pool[id(self)].isSet(): return False
-
- output(u'%s Starving' % self)
- self.CheckUsage.close()
- del self.pool[id(self)]
- self.pool.threads.remove(self)
- return True
- finally:
- self.pool.jobLock.release()
-
+ timeout = 120
+ def __init__(self, pool, CommonsDelinker):
+ threadpool.Thread.__init__(self, pool)
+ self.CommonsDelinker = CommonsDelinker
+ # Not really thread safe, but we should only do read operations...
+ self.site = CommonsDelinker.site
+
+ def run(self):
+ try:
+ self.connect()
+ except:
+ return self.exit()
+ threadpool.Thread.run(self)
+
+ def connect(self):
+ output(u'%s Connecting to databases' % self)
+ config = self.CommonsDelinker.config
+ if config['global']:
+ # Note: global use requires MySQL
+ self.CheckUsage = checkusage.CheckUsage(limit = sys.maxint,
+ mysql_kwargs = config['sql_config'],
+ use_autoconn = True,
+ http_callback = wait_callback,
+ mysql_callback = wait_callback)
+ else:
+ self.CheckUsage = checkusage.CheckUsage(sys.maxint,
+ http_callback = wait_callback, no_db = True)
+
+
+ def check_usage(self, image, timestamp, admin, reason, replacement):
+ """ Check whether this image needs to be delinked.
"""
+
+ # Check whether the image still is deleted on Commons.
+ # BUG: This also returns true for images with a page, but
+ # without the image itself. Can be fixed by querying query.php
+ # instead of api.php. Also should this be made as an exits()
+ # method of checkusage.CheckUsage?
+ if self.site.shared_image_repository() != (None, None):
+ shared_image_repository =
self.CommonsDelinker.get_site(*self.site.shared_image_repository())
+ try:
+ if self.CheckUsage.exists(shared_image_repository, image) \
+ and not bool(replacement):
+ output(u'%s %s exists on the shared image repository!' %
(self, image))
+ return
+ finally:
+ self.CommonsDelinker.unlock_site(shared_image_repository)
+ if self.CheckUsage.exists(self.site, image) and \
+ not bool(replacement):
+ output(u'%s %s exists again!' % (self, image))
+ return
+
+
+ if self.CommonsDelinker.config['global']:
+ usage = self.CheckUsage.get_usage(image)
+ usage_domains = {}
+
+ count = 0
+ # Sort usage per domain
+ for (lang, family), (page_namespace, page_title, title) in usage:
+ if (lang, family) not in usage_domains:
+ usage_domains[(lang, family)] = []
+ usage_domains[(lang, family)].append((page_namespace, page_title,
title))
+ count += 1
+ else:
+ #FIX!
+ usage_domains = {(self.site.lang, self.site.family.name):
+ list(self.CheckUsage.get_usage_live(self.site,
+ image))}
+ count = len(usage_domains[(self.site.lang, self.site.family.name)])
+
+ output(u'%s %s used on %s pages' % (self, image, count))
+
+ if count:
+ # Pass the usage to the Delinker pool along with other arguments
+ self.CommonsDelinker.Delinkers.append((image, usage_domains,
+ timestamp, admin, reason, replacement))
+ elif replacement:
+ # Record replacement done
+ self.CommonsDelinker.Loggers.append((timestamp, image, replacement))
+
+ def do(self, args):
+ try:
+ self.check_usage(*args)
+ except:
+ # Something unexpected happened. Report and die.
+ output('An exception occured in %s' % self, False)
+ traceback.print_exc(file = sys.stderr)
+ self.exit()
+ self.CommonsDelinker.thread_died()
+
+ def starve(self):
+ self.pool.jobLock.acquire()
+ try:
+ if self.pool[id(self)].isSet(): return False
+
+ output(u'%s Starving' % self)
+ self.CheckUsage.close()
+ del self.pool[id(self)]
+ self.pool.threads.remove(self)
+ return True
+ finally:
+ self.pool.jobLock.release()
+
class Logger(threadpool.Thread):
- timeout = 360
-
- def __init__(self, pool, CommonsDelinker):
- threadpool.Thread.__init__(self, pool)
- self.CommonsDelinker = CommonsDelinker
- self.sql_layout = self.CommonsDelinker.config.get('sql_layout', 'new')
- self.enabled = self.CommonsDelinker.config.get('enable_logging', True)
-
- def run(self):
- self.connect()
- threadpool.Thread.run(self)
-
- def connect(self):
- output(u'%s Connecting to log database' % self)
- self.database = connect_database()
- self.cursor = self.database.cursor()
-
-
- def log_result_legacy(self, timestamp, image, domain, namespace, page, status =
"ok", newimage = None):
- # TODO: Make sqlite3 ready
-
- # The original delinker code cached log results,
- # in order to limit the number of connections.
- # However, since we are now using persistent
- # connections, we can safely insert the result
- # on the fly.
- output(u'%s Logging %s for %s on %s' % (self, repr(status), image, page))
-
- # There is no need to escape each parameter if
- # a parametrized call is made.
- self.cursor.execute("""INSERT INTO %s (timestamp, img, wiki,
page_title,
- namespace, status, newimg) VALUES
- (%%s, %%s, %%s, %%s, %%s, %%s, %%s)""" %
self.CommonsDelinker.config['log_table'],
- (timestamp, image, domain, page, namespace, status, newimage))
- self.database.commit()
-
- def log_result_new(self, timestamp, image, site_lang, site_family,
- page_namespace, page_title, status = 'ok', new_image = None):
-
- output(u'%s Logging %s for %s on %s' % (self, repr(status), image,
page_title))
+ timeout = 360
+
+ def __init__(self, pool, CommonsDelinker):
+ threadpool.Thread.__init__(self, pool)
+ self.CommonsDelinker = CommonsDelinker
+ self.sql_layout = self.CommonsDelinker.config.get('sql_layout',
'new')
+ self.enabled = self.CommonsDelinker.config.get('enable_logging', True)
+
+ def run(self):
+ self.connect()
+ threadpool.Thread.run(self)
+
+ def connect(self):
+ output(u'%s Connecting to log database' % self)
+ self.database = connect_database()
+ self.cursor = self.database.cursor()
+
+
+ def log_result_legacy(self, timestamp, image, domain, namespace, page, status =
"ok", newimage = None):
+ # TODO: Make sqlite3 ready
+
+ # The original delinker code cached log results,
+ # in order to limit the number of connections.
+ # However, since we are now using persistent
+ # connections, we can safely insert the result
+ # on the fly.
+ output(u'%s Logging %s for %s on %s' % (self, repr(status), image,
page))
+
+ # There is no need to escape each parameter if
+ # a parametrized call is made.
+ self.cursor.execute("""INSERT INTO %s (timestamp, img, wiki,
page_title,
+ namespace, status, newimg) VALUES
+ (%%s, %%s, %%s, %%s, %%s, %%s, %%s)""" %
self.CommonsDelinker.config['log_table'],
+ (timestamp, image, domain, page, namespace, status, newimage))
+ self.database.commit()
+
+ def log_result_new(self, timestamp, image, site_lang, site_family,
+ page_namespace, page_title, status = 'ok', new_image = None):
+
+ output(u'%s Logging %s for %s on %s' % (self, repr(status), image,
page_title))
- self.cursor.execute("""INSERT INTO %s (timestamp, image, site_lang,
site_family,
- page_namespace, page_title, status, new_image) VALUES
- (%%s, %%s, %%s, %%s, %%s, %%s, %%s, %%s)""" %
self.CommonsDelinker.config['log_table'],
- (timestamp, image, site_lang, site_family, page_namespace, page_title,
- status, new_image))
- self.database.commit()
-
- def log_replacement(self, timestamp, old_image, new_image):
- # TODO: Same as above
-
- output(u'Replacing %s by %s done' % (old_image, new_image))
- self.cursor.execute("""UPDATE %s SET status = 'done' WHERE
- timestamp = %%s AND old_image = %%s AND
- new_image = %%s""" %
self.CommonsDelinker.config['replacer_table'],
- (timestamp, old_image, new_image))
- self.database.commit()
-
- def do(self, args):
- if not self.enabled: return
- try:
- if len(args) == 3:
- self.log_replacement(*args)
- else:
- if self.sql_layout == 'new':
- self.log_result_new(*args)
- else:
- self.log_result_legacy(*args)
- except:
- # Something unexpected happened. Report and die.
- output('An exception occured in %s' % self, False)
- traceback.print_exc(file = sys.stderr)
- self.exit()
- self.CommonsDelinker.thread_died()
-
- def starve(self):
- self.pool.jobLock.acquire()
- try:
- if self.pool[id(self)].isSet(): return False
-
- output(u'%s Starving' % self)
- self.database.close()
- del self.pool[id(self)]
- self.pool.threads.remove(self)
- return True
- finally:
- self.pool.jobLock.release()
+ self.cursor.execute("""INSERT INTO %s (timestamp, image,
site_lang, site_family,
+ page_namespace, page_title, status, new_image) VALUES
+ (%%s, %%s, %%s, %%s, %%s, %%s, %%s, %%s)""" %
self.CommonsDelinker.config['log_table'],
+ (timestamp, image, site_lang, site_family, page_namespace, page_title,
+ status, new_image))
+ self.database.commit()
+
+ def log_replacement(self, timestamp, old_image, new_image):
+ # TODO: Same as above
+
+ output(u'Replacing %s by %s done' % (old_image, new_image))
+ self.cursor.execute("""UPDATE %s SET status = 'done' WHERE
+ timestamp = %%s AND old_image = %%s AND
+ new_image = %%s""" %
self.CommonsDelinker.config['replacer_table'],
+ (timestamp, old_image, new_image))
+ self.database.commit()
+
+ def do(self, args):
+ if not self.enabled: return
+ try:
+ if len(args) == 3:
+ self.log_replacement(*args)
+ else:
+ if self.sql_layout == 'new':
+ self.log_result_new(*args)
+ else:
+ self.log_result_legacy(*args)
+ except:
+ # Something unexpected happened. Report and die.
+ output('An exception occured in %s' % self, False)
+ traceback.print_exc(file = sys.stderr)
+ self.exit()
+ self.CommonsDelinker.thread_died()
+
+ def starve(self):
+ self.pool.jobLock.acquire()
+ try:
+ if self.pool[id(self)].isSet(): return False
+
+ output(u'%s Starving' % self)
+ self.database.close()
+ del self.pool[id(self)]
+ self.pool.threads.remove(self)
+ return True
+ finally:
+ self.pool.jobLock.release()
class CommonsDelinker(object):
- def __init__(self):
- self.config = config.CommonsDelinker
- self.site = wikipedia.getSite()
- self.site.forceLogin()
-
- # Initialize workers
- self.CheckUsages = threadpool.ThreadPool(CheckUsage,
self.config['checkusage_instances'], self)
- self.Delinkers = threadpool.ThreadPool(Delinker,
self.config['delinker_instances'], self)
- if self.config.get('enable_logging', True):
- self.Loggers = threadpool.ThreadPool(Logger, self.config['logger_instances'],
self)
- else:
- self.Loggers = threadpool.ThreadPool(Logger, 1, self)
-
- self.http = checkusage.HTTP(self.site.hostname())
-
- self.edit_list = []
- self.editLock = threading.Lock()
-
- self.sites = {}
- self.siteLock = threading.Lock()
-
- self.SummaryCache = SummaryCache(self)
-
- if self.config.get('enable_replacer', False):
- self.connect_mysql()
-
- if self.config.get('no_sysop', False):
- # Don't edit as sysop
- if hasattr(config, 'sysopnames'):
- config.sysopnames = dict([(fam, {}) for fam in config.sysopnames.keys()])
-
- self.last_check = time.time()
-
- #if 'bot' in self.site.userGroups:
- # self.log_limit = '5000'
- #else:
- # self.log_limit = '500'
- self.log_limit = '500'
- self.init_plugins()
-
- def init_plugins(self, do_reload = False):
- import plugins
- self.hooks = {}
- for item in self.config.get('plugins', ()):
- mname, name = item.split('.', 1)
- __import__('plugins.' + mname)
- module = getattr(plugins, mname)
- if do_reload: module = reload(module)
- plugin = getattr(module, name)
- if type(plugin) is type:
- plugin = plugin(self)
- if plugin.hook not in self.hooks:
- self.hooks[plugin.hook] = []
- self.hooks[plugin.hook].append(plugin)
- output(u"%s Loaded plugin %s for hook '%s'" % \
- (self, plugin, plugin.hook))
-
- def exec_hook(self, name, args):
- # TODO: Threadsafety!
- if name in self.hooks:
- self.siteLock.acquire()
- try:
- plugins = self.hooks[name][:]
- finally:
- self.siteLock.release()
- for plugin in plugins:
- try:
- if plugin(*args) is False:
- return False
- except Exception, e:
- if type(e) in (SystemExit, KeyboardInterrupt):
- raise
- self.siteLock.acquire()
- try:
- output('Warning! Error executing hook %s' % plugin, False)
- output('%s: %s' % (e.__class__.__name__, str(e)), False)
- traceback.print_exc(file = sys.stderr)
- self.hooks[name].remove(plugin)
- finally:
- self.siteLock.release()
-
- def reload_plugins(signalnum, stack):
- pass
-
- def connect_mysql(self):
- self.database = connect_database()
- self.cursor = self.database.cursor()
-
- def set_edit(self, domain, page):
- """ Make sure the bot does not create edit
- conflicts with itself."""
- self.editLock.acquire()
- being_editted = (domain, page) in self.edit_list
- if not being_editted:
- self.edit_list.append((domain, page))
- self.editLock.release()
- return being_editted
- def unset_edit(self, domain, page):
- """ Done editting. """
- self.editLock.acquire()
- self.edit_list.remove((domain, page))
- self.editLock.release()
-
- def get_site(self, code, fam):
- # Threadsafe replacement of wikipedia.getSite
- key = '%s:%s' % (code, fam)
- self.siteLock.acquire()
- try:
- if key not in self.sites:
- self.sites[key] = []
- for site, used in self.sites[key]:
- if not site: return False
- if not used:
- self.sites[key][self.sites[key].index((site, False))] = (site, True)
- return site
- try:
- site = wikipedia.getSite(code, fam)
- except wikipedia.NoSuchSite:
- site = False
- self.sites[key].append((site, True))
- return site
- finally:
- self.siteLock.release()
- def unlock_site(self, site):
- key = '%s:%s' % (site.lang, site.family.name)
- self.siteLock.acquire()
- try:
- self.sites[key][self.sites[key].index((site, True))] = (site, False)
- finally:
- self.siteLock.release()
-
-
- def read_deletion_log(self):
- ts_format = '%Y-%m-%dT%H:%M:%SZ'
- wait = self.config['delink_wait']
- exclusion = self.config['exclude_string']
-
- ts_from = self.last_check
- # Truncate -> int()
- ts_end = int(time.time())
- self.last_check = ts_end
-
- # Format as a Mediawiki timestamp and substract a
- # certain wait period.
- ts_from_s = time.strftime(ts_format, time.gmtime(ts_from - wait + 1))
- ts_end_s = time.strftime(ts_format, time.gmtime(ts_end - wait))
-
- try:
- # Assume less than 500 deletion have been made between
- # this and the previous check of the log. If this is not
- # the case, timeout should be set lower.
- result = self.http.query_api(self.site.hostname(), self.site.apipath(),
- action = 'query', list = 'logevents', letype = 'delete',
- lelimit = self.log_limit, lestart = ts_from_s, leend = ts_end_s,
- ledir = 'newer')
- logevents = result['query']['logevents']
- except Exception, e:
- if type(e) in (SystemError, KeyboardInterrupt): raise
- # Something happened, but since it is a network error,
- # it will not be critical. In order to prevent data loss
- # the last_check timestamp has to be set correctly.
- self.last_check = ts_from
- output('Warning! Unable to read deletion logs', False)
- output('%s: %s' % (e.__class__.__name__, str(e)), False)
- return time.sleep(self.config['timeout'])
-
- for logevent in logevents:
- if logevent['ns'] == 6 and logevent['action'] == 'delete':
- if exclusion not in logevent.get('comment', ''):
- timestamp = logevent['timestamp']
- timestamp = timestamp.replace('-', '')
- timestamp = timestamp.replace(':', '')
- timestamp = timestamp.replace('T', '')
- timestamp = timestamp.replace('Z', '')
-
- output(u'Deleted image: %s' % logevent['title'])
- self.CheckUsages.append((checkusage.strip_ns(logevent['title']),
- timestamp, logevent['user'], logevent.get('comment', ''),
- None))
- else:
- output(u'Skipping deleted image: %s' % logevent['title'])
-
- def read_replacement_log(self):
- # TODO: Make sqlite3 ready
- # TODO: Single process replacer
- update = """UPDATE %s SET status = %%s WHERE id = %%s"""
% \
- self.config['replacer_table']
- self.cursor.execute("""SELECT id, timestamp, old_image, new_image, user,
comment
- FROM %s WHERE status = 'pending'""" %
self.config['replacer_table'])
- result = ([universal_unicode(s) for s in i] for i in self.cursor.fetchall())
+ def __init__(self):
+ self.config = config.CommonsDelinker
+ self.site = wikipedia.getSite()
+ self.site.forceLogin()
+
+ # Initialize workers
+ self.CheckUsages = threadpool.ThreadPool(CheckUsage,
self.config['checkusage_instances'], self)
+ self.Delinkers = threadpool.ThreadPool(Delinker,
self.config['delinker_instances'], self)
+ if self.config.get('enable_logging', True):
+ self.Loggers = threadpool.ThreadPool(Logger,
self.config['logger_instances'], self)
+ else:
+ self.Loggers = threadpool.ThreadPool(Logger, 1, self)
+
+ self.http = checkusage.HTTP(self.site.hostname())
+
+ self.edit_list = []
+ self.editLock = threading.Lock()
+
+ self.sites = {}
+ self.siteLock = threading.Lock()
+
+ self.SummaryCache = SummaryCache(self)
+
+ if self.config.get('enable_replacer', False):
+ self.connect_mysql()
+
+ if self.config.get('no_sysop', False):
+ # Don't edit as sysop
+ if hasattr(config, 'sysopnames'):
+ config.sysopnames = dict([(fam, {}) for fam in
config.sysopnames.keys()])
+
+ self.last_check = time.time()
+
+ #if 'bot' in self.site.userGroups:
+ # self.log_limit = '5000'
+ #else:
+ # self.log_limit = '500'
+ self.log_limit = '500'
+ self.init_plugins()
+
+ def init_plugins(self, do_reload = False):
+ import plugins
+ self.hooks = {}
+ for item in self.config.get('plugins', ()):
+ mname, name = item.split('.', 1)
+ __import__('plugins.' + mname)
+ module = getattr(plugins, mname)
+ if do_reload: module = reload(module)
+ plugin = getattr(module, name)
+ if type(plugin) is type:
+ plugin = plugin(self)
+ if plugin.hook not in self.hooks:
+ self.hooks[plugin.hook] = []
+ self.hooks[plugin.hook].append(plugin)
+ output(u"%s Loaded plugin %s for hook '%s'" % \
+ (self, plugin, plugin.hook))
+
+ def exec_hook(self, name, args):
+ # TODO: Threadsafety!
+ if name in self.hooks:
+ self.siteLock.acquire()
+ try:
+ plugins = self.hooks[name][:]
+ finally:
+ self.siteLock.release()
+ for plugin in plugins:
+ try:
+ if plugin(*args) is False:
+ return False
+ except Exception, e:
+ if type(e) in (SystemExit, KeyboardInterrupt):
+ raise
+ self.siteLock.acquire()
+ try:
+ output('Warning! Error executing hook %s' % plugin,
False)
+ output('%s: %s' % (e.__class__.__name__, str(e)), False)
+ traceback.print_exc(file = sys.stderr)
+ self.hooks[name].remove(plugin)
+ finally:
+ self.siteLock.release()
+
+ def reload_plugins(signalnum, stack):
+ pass
+
+ def connect_mysql(self):
+ self.database = connect_database()
+ self.cursor = self.database.cursor()
+
+ def set_edit(self, domain, page):
+ """ Make sure the bot does not create edit
+ conflicts with itself."""
+ self.editLock.acquire()
+ being_editted = (domain, page) in self.edit_list
+ if not being_editted:
+ self.edit_list.append((domain, page))
+ self.editLock.release()
+ return being_editted
+ def unset_edit(self, domain, page):
+ """ Done editting. """
+ self.editLock.acquire()
+ self.edit_list.remove((domain, page))
+ self.editLock.release()
+
+ def get_site(self, code, fam):
+ # Threadsafe replacement of wikipedia.getSite
+ key = '%s:%s' % (code, fam)
+ self.siteLock.acquire()
+ try:
+ if key not in self.sites:
+ self.sites[key] = []
+ for site, used in self.sites[key]:
+ if not site: return False
+ if not used:
+ self.sites[key][self.sites[key].index((site, False))] = (site, True)
+ return site
+ try:
+ site = wikipedia.getSite(code, fam)
+ except wikipedia.NoSuchSite:
+ site = False
+ self.sites[key].append((site, True))
+ return site
+ finally:
+ self.siteLock.release()
+ def unlock_site(self, site):
+ key = '%s:%s' % (site.lang, site.family.name)
+ self.siteLock.acquire()
+ try:
+ self.sites[key][self.sites[key].index((site, True))] = (site, False)
+ finally:
+ self.siteLock.release()
+
+
+ def read_deletion_log(self):
+ ts_format = '%Y-%m-%dT%H:%M:%SZ'
+ wait = self.config['delink_wait']
+ exclusion = self.config['exclude_string']
+
+ ts_from = self.last_check
+ # Truncate -> int()
+ ts_end = int(time.time())
+ self.last_check = ts_end
+
+ # Format as a Mediawiki timestamp and substract a
+ # certain wait period.
+ ts_from_s = time.strftime(ts_format, time.gmtime(ts_from - wait + 1))
+ ts_end_s = time.strftime(ts_format, time.gmtime(ts_end - wait))
+
+ try:
+ # Assume less than 500 deletion have been made between
+ # this and the previous check of the log. If this is not
+ # the case, timeout should be set lower.
+ result = self.http.query_api(self.site.hostname(), self.site.apipath(),
+ action = 'query', list = 'logevents', letype =
'delete',
+ lelimit = self.log_limit, lestart = ts_from_s, leend = ts_end_s,
+ ledir = 'newer')
+ logevents = result['query']['logevents']
+ except Exception, e:
+ if type(e) in (SystemError, KeyboardInterrupt): raise
+ # Something happened, but since it is a network error,
+ # it will not be critical. In order to prevent data loss
+ # the last_check timestamp has to be set correctly.
+ self.last_check = ts_from
+ output('Warning! Unable to read deletion logs', False)
+ output('%s: %s' % (e.__class__.__name__, str(e)), False)
+ return time.sleep(self.config['timeout'])
+
+ for logevent in logevents:
+ if logevent['ns'] == 6 and logevent['action'] ==
'delete':
+ if exclusion not in logevent.get('comment', ''):
+ timestamp = logevent['timestamp']
+ timestamp = timestamp.replace('-', '')
+ timestamp = timestamp.replace(':', '')
+ timestamp = timestamp.replace('T', '')
+ timestamp = timestamp.replace('Z', '')
+
+ output(u'Deleted image: %s' % logevent['title'])
+
self.CheckUsages.append((checkusage.strip_ns(logevent['title']),
+ timestamp, logevent['user'],
logevent.get('comment', ''),
+ None))
+ else:
+ output(u'Skipping deleted image: %s' %
logevent['title'])
+
+ def read_replacement_log(self):
+ # TODO: Make sqlite3 ready
+ # TODO: Single process replacer
+ update = """UPDATE %s SET status = %%s WHERE id =
%%s""" % \
+ self.config['replacer_table']
+ self.cursor.execute("""SELECT id, timestamp, old_image, new_image,
user, comment
+ FROM %s WHERE status = 'pending'""" %
self.config['replacer_table'])
+ result = ([universal_unicode(s) for s in i] for i in self.cursor.fetchall())
- for id, timestamp, old_image, new_image, user, comment in result:
- self.CheckUsages.append((old_image, timestamp, user, comment, new_image))
- output(u'Replacing %s by %s' % (old_image, new_image))
- self.cursor.execute(update, ('ok', id))
-
- self.database.commit()
-
- def start(self):
- # Gracefully exit all threads on SIG_INT or SIG_TERM
- threadpool.catch_signals()
-
- # Start threads
- self.Loggers.start()
- self.Delinkers.start()
- self.CheckUsages.start()
-
- # Give threads some time to initialize
- time.sleep(self.config['timeout'])
- output(u'All workers started')
-
- # Main loop
- while True:
- if self.config.get('enable_delinker', True):
- if 'deletion_log_table' in self.config:
- if not self.read_deletion_log_db():
- self.read_deletion_log()
- else:
- self.read_deletion_log()
- if self.config.get('enable_replacer', False):
- self.read_replacement_log()
-
- time.sleep(self.config['timeout'])
-
- def thread_died(self):
- # Obsolete
- return
-
- @staticmethod
- def output(*args):
- return output(*args)
-
+ for id, timestamp, old_image, new_image, user, comment in result:
+ self.CheckUsages.append((old_image, timestamp, user, comment, new_image))
+ output(u'Replacing %s by %s' % (old_image, new_image))
+ self.cursor.execute(update, ('ok', id))
+
+ self.database.commit()
+
+ def start(self):
+ # Gracefully exit all threads on SIG_INT or SIG_TERM
+ threadpool.catch_signals()
+
+ # Start threads
+ self.Loggers.start()
+ self.Delinkers.start()
+ self.CheckUsages.start()
+
+ # Give threads some time to initialize
+ time.sleep(self.config['timeout'])
+ output(u'All workers started')
+
+ # Main loop
+ while True:
+ if self.config.get('enable_delinker', True):
+ if 'deletion_log_table' in self.config:
+ if not self.read_deletion_log_db():
+ self.read_deletion_log()
+ else:
+ self.read_deletion_log()
+ if self.config.get('enable_replacer', False):
+ self.read_replacement_log()
+
+ time.sleep(self.config['timeout'])
+
+ def thread_died(self):
+ # Obsolete
+ return
+
+ @staticmethod
+ def output(*args):
+ return output(*args)
+
def output(message, toStdout = True):
- message = time.strftime('[%Y-%m-%d %H:%M:%S] ') + message
- wikipedia.output(message, toStdout = toStdout)
- if toStdout:
- sys.stdout.flush()
- else:
- sys.stderr.flush()
+ message = time.strftime('[%Y-%m-%d %H:%M:%S] ') + message
+ wikipedia.output(message, toStdout = toStdout)
+ if toStdout:
+ sys.stdout.flush()
+ else:
+ sys.stderr.flush()
def main():
- global CD
- output(u'Running ' + __version__)
- CD = CommonsDelinker()
- output(u'This bot runs from: ' + str(CD.site))
-
- re._MAXCACHE = 4
-
- args = wikipedia.handleArgs()
- if '-since' in args:
- # NOTE: Untested
- ts_format = '%Y-%m-%d %H:%M:%S'
- try:
- since = time.strptime(
- args[args.index('-since') + 1],
- ts_format)
- except ValueError:
- if args[args.index('-since') + 1][0] == '[' and \
- len(args) != args.index('-since') + 2:
- since = time.strptime('%s %s' % \
- args[args.index('-since') + 1],
- '[%s]' % ts_format)
- else:
- raise ValueError('Incorrect time format!')
- output(u'Reading deletion log since [%s]' %\
- time.strftime(ts_format, since))
- CD.last_check = time.mktime(since)
-
- try:
- try:
- CD.start()
- except Exception, e:
- if type(e) not in (SystemExit, KeyboardInterrupt):
- output('An exception occured in the main thread!', False)
- traceback.print_exc(file = sys.stderr)
- threadpool.terminate()
- finally:
- output(u'Stopping CommonsDelinker')
- wikipedia.stopme()
- # Flush the standard streams
- sys.stdout.flush()
- sys.stderr.flush()
+ global CD
+ output(u'Running ' + __version__)
+ CD = CommonsDelinker()
+ output(u'This bot runs from: ' + str(CD.site))
+
+ re._MAXCACHE = 4
+
+ args = wikipedia.handleArgs()
+ if '-since' in args:
+ # NOTE: Untested
+ ts_format = '%Y-%m-%d %H:%M:%S'
+ try:
+ since = time.strptime(
+ args[args.index('-since') + 1],
+ ts_format)
+ except ValueError:
+ if args[args.index('-since') + 1][0] == '[' and \
+ len(args) != args.index('-since') + 2:
+ since = time.strptime('%s %s' % \
+ args[args.index('-since') + 1],
+ '[%s]' % ts_format)
+ else:
+ raise ValueError('Incorrect time format!')
+ output(u'Reading deletion log since [%s]' %\
+ time.strftime(ts_format, since))
+ CD.last_check = time.mktime(since)
+
+ try:
+ try:
+ CD.start()
+ except Exception, e:
+ if type(e) not in (SystemExit, KeyboardInterrupt):
+ output('An exception occured in the main thread!', False)
+ traceback.print_exc(file = sys.stderr)
+ threadpool.terminate()
+ finally:
+ output(u'Stopping CommonsDelinker')
+ wikipedia.stopme()
+ # Flush the standard streams
+ sys.stdout.flush()
+ sys.stderr.flush()
if __name__ == '__main__': main()
Modified: trunk/pywikipedia/commonsdelinker/image_replacer.py
===================================================================
--- trunk/pywikipedia/commonsdelinker/image_replacer.py 2009-03-24 01:15:12 UTC (rev
6539)
+++ trunk/pywikipedia/commonsdelinker/image_replacer.py 2009-03-24 01:15:50 UTC (rev
6540)
@@ -19,281 +19,281 @@
from checkusage import family
def mw_timestamp(ts):
- return '%s%s%s%s-%s%s-%s%sT%s%s:%s%s:%s%sZ' % tuple(ts)
+ return '%s%s%s%s-%s%s-%s%sT%s%s:%s%s:%s%sZ' % tuple(ts)
DB_TS = re.compile('[^0-9]')
def db_timestamp(ts):
- return DB_TS.sub('', ts)
+ return DB_TS.sub('', ts)
IMG_NS = re.compile(r'(?i)^\s*File\:')
def strip_image(img):
- img = IMG_NS.sub('', img)
- img = img.replace(' ', '_')
- img = img[0].upper() + img[1:]
- return img.strip()
+ img = IMG_NS.sub('', img)
+ img = img.replace(' ', '_')
+ img = img[0].upper() + img[1:]
+ return img.strip()
def site_prefix(site):
- if site.lang == site.family.name:
- return site.lang
- if (site.lang, site.family.name) == ('-', 'wikisource'):
- return 'oldwikisource'
- return '%s:%s' % (site.family.name, site.lang)
+ if site.lang == site.family.name:
+ return site.lang
+ if (site.lang, site.family.name) == ('-', 'wikisource'):
+ return 'oldwikisource'
+ return '%s:%s' % (site.family.name, site.lang)
class Replacer(object):
- def __init__(self):
- self.config = config.CommonsDelinker
- self.config.update(getattr(config, 'Replacer', ()))
- self.template =
re.compile(r'\{\{%s\|([^|]*?)\|([^|]*?)(?:(?:\|reason\=(.*?))?)\}\}' % \
- self.config['replace_template'])
- self.disallowed_replacements = [(re.compile(i[0], re.I), re.compile(i[1], re.I))
- for i in self.config.get('disallowed_replacements', ())]
-
- self.site = wikipedia.getSite(persistent_http = True)
- self.site.forceLogin()
-
- self.database = connect_database()
- self.cursor = self.database.cursor()
-
- self.first_revision = 0
- if self.config.get('replacer_report_replacements', False):
- self.reporters = threadpool.ThreadPool(Reporter, 1, self.site, self.config)
- self.reporters.start()
-
-
- def read_replace_log(self):
- # FIXME: Make sqlite3 compatible
- insert = """INSERT INTO %s (timestamp, old_image, new_image,
- status, user, comment) VALUES (%%s, %%s, %%s,
- 'pending', %%s, %%s)""" %
self.config['replacer_table']
-
- page = wikipedia.Page(self.site, self.config['command_page'])
-
- # Get last revision date
- if self.cursor.execute("""SELECT timestamp FROM %s
- ORDER BY timestamp DESC LIMIT 1""" % \
- self.config['replacer_table']):
- since = mw_timestamp(self.cursor.fetchone()[0])
- else:
- since = None
-
- if self.config.get('clean_list', False):
- username = config.sysopnames[self.site.family.name][self.site.lang]
- else:
- username = None
-
- try:
- revisions = self.get_history(page.title(), since, username)
- # Fetch the page any way, to prevent editconflicts
- old_text = text = page.get()
- except (SystemExit, KeyboardInterrupt):
- raise
- except Exception, e:
- # Network error, not critical
- output(u'Warning! Unable to read replacement log.', False)
- output('%s: %s' % (e.__class__.__name__, str(e)), False)
- #self.site.conn.close()
- #self.site.conn.connect()
- return time.sleep(self.config['timeout'])
-
- if '{{stop}}' in text.lower():
- output(u'Found {{stop}} on command page. Not replacing anything.')
- return time.sleep(self.config['timeout'])
-
- revisions.sort(key = lambda rev: rev['timestamp'])
- replacements = self.template.finditer(text)
-
- remove_from_list = []
- count = 0
- for replacement in replacements:
- if count == self.config.get('replacer_rate_limit', -1): break
- res = self.examine_revision_history(
- revisions, replacement, username)
- if res and self.allowed_replacement(replacement) and \
- replacement.group(1) != replacement.group(2):
- self.cursor.execute(insert, res)
- remove_from_list.append(replacement.group(0))
- output('Replacing %s by %s: %s' % replacement.groups())
- count += 1
- self.database.commit()
-
- if remove_from_list and self.config.get('clean_list', False):
- while True:
- try:
- for remove in remove_from_list:
- text = text.replace(remove, u'')
- page.put(text.strip(), comment = 'Removing images being processed')
- return
- except wikipedia.EditConflict:
- text = page.get()
-
- def get_history(self, title, since, username):
- address = self.site.api_address()
- predata = [
- ('action', 'query'),
- ('prop', 'revisions'),
- ('titles', title.encode('utf-8')),
- ('rvprop', 'timestamp|user|comment|content'),
- ('rvlimit', '50'),
- ('format', 'json'),
- ]
- if username:
- predata.append(('rvexcludeuser', username.encode('utf-8')))
- if since:
- predata.append(('rvend', since))
- response, data = self.site.postForm(address, predata)
- data = simplejson.loads(data)
- if 'error' in data:
- raise RuntimeError(data['error'])
+ def __init__(self):
+ self.config = config.CommonsDelinker
+ self.config.update(getattr(config, 'Replacer', ()))
+ self.template =
re.compile(r'\{\{%s\|([^|]*?)\|([^|]*?)(?:(?:\|reason\=(.*?))?)\}\}' % \
+ self.config['replace_template'])
+ self.disallowed_replacements = [(re.compile(i[0], re.I), re.compile(i[1], re.I))
+ for i in self.config.get('disallowed_replacements', ())]
+
+ self.site = wikipedia.getSite(persistent_http = True)
+ self.site.forceLogin()
+
+ self.database = connect_database()
+ self.cursor = self.database.cursor()
+
+ self.first_revision = 0
+ if self.config.get('replacer_report_replacements', False):
+ self.reporters = threadpool.ThreadPool(Reporter, 1, self.site, self.config)
+ self.reporters.start()
+
+
+ def read_replace_log(self):
+ # FIXME: Make sqlite3 compatible
+ insert = """INSERT INTO %s (timestamp, old_image, new_image,
+ status, user, comment) VALUES (%%s, %%s, %%s,
+ 'pending', %%s, %%s)""" %
self.config['replacer_table']
+
+ page = wikipedia.Page(self.site, self.config['command_page'])
+
+ # Get last revision date
+ if self.cursor.execute("""SELECT timestamp FROM %s
+ ORDER BY timestamp DESC LIMIT 1""" % \
+ self.config['replacer_table']):
+ since = mw_timestamp(self.cursor.fetchone()[0])
+ else:
+ since = None
+
+ if self.config.get('clean_list', False):
+ username = config.sysopnames[self.site.family.name][self.site.lang]
+ else:
+ username = None
+
+ try:
+ revisions = self.get_history(page.title(), since, username)
+ # Fetch the page any way, to prevent editconflicts
+ old_text = text = page.get()
+ except (SystemExit, KeyboardInterrupt):
+ raise
+ except Exception, e:
+ # Network error, not critical
+ output(u'Warning! Unable to read replacement log.', False)
+ output('%s: %s' % (e.__class__.__name__, str(e)), False)
+ #self.site.conn.close()
+ #self.site.conn.connect()
+ return time.sleep(self.config['timeout'])
+
+ if '{{stop}}' in text.lower():
+ output(u'Found {{stop}} on command page. Not replacing anything.')
+ return time.sleep(self.config['timeout'])
+
+ revisions.sort(key = lambda rev: rev['timestamp'])
+ replacements = self.template.finditer(text)
+
+ remove_from_list = []
+ count = 0
+ for replacement in replacements:
+ if count == self.config.get('replacer_rate_limit', -1): break
+ res = self.examine_revision_history(
+ revisions, replacement, username)
+ if res and self.allowed_replacement(replacement) and \
+ replacement.group(1) != replacement.group(2):
+ self.cursor.execute(insert, res)
+ remove_from_list.append(replacement.group(0))
+ output('Replacing %s by %s: %s' % replacement.groups())
+ count += 1
+ self.database.commit()
+
+ if remove_from_list and self.config.get('clean_list', False):
+ while True:
+ try:
+ for remove in remove_from_list:
+ text = text.replace(remove, u'')
+ page.put(text.strip(), comment = 'Removing images being
processed')
+ return
+ except wikipedia.EditConflict:
+ text = page.get()
+
+ def get_history(self, title, since, username):
+ address = self.site.api_address()
+ predata = [
+ ('action', 'query'),
+ ('prop', 'revisions'),
+ ('titles', title.encode('utf-8')),
+ ('rvprop', 'timestamp|user|comment|content'),
+ ('rvlimit', '50'),
+ ('format', 'json'),
+ ]
+ if username:
+ predata.append(('rvexcludeuser', username.encode('utf-8')))
+ if since:
+ predata.append(('rvend', since))
+ response, data = self.site.postForm(address, predata)
+ data = simplejson.loads(data)
+ if 'error' in data:
+ raise RuntimeError(data['error'])
- page = data['query']['pages'].values()[0]
- if 'missing' in page:
- raise Exception('Missing page!')
- return page.get('revisions', [])
-
- def examine_revision_history(self, revisions, replacement, username):
- for revision in revisions:
- if replacement.group(0) in revision['*']:
- db_time = db_timestamp(revision['timestamp'])
- if db_time < self.first_revision or not self.first_revision:
- self.first_revision = int(db_time)
- return (db_time, strip_image(replacement.group(1)),
- strip_image(replacement.group(2)),
- revision['user'], replacement.group(3))
-
- output('Warning! Could not find out who did %s' % \
- repr(replacement.group(0)), False)
- return
-
- def read_finished_replacements(self):
- self.cursor.execute('START TRANSACTION WITH CONSISTENT SNAPSHOT')
- self.cursor.execute("""SELECT old_image, new_image, user, comment FROM
- %s WHERE status = 'done' AND timestamp >= %i""" % \
- (self.config['replacer_table'], self.first_revision))
- finished_images = list(self.cursor)
- self.cursor.execute("""UPDATE %s SET status = 'reported'
- WHERE status = 'done' AND timestamp >= %i""" % \
- (self.config['replacer_table'], self.first_revision))
- self.cursor.commit()
-
- for old_image, new_image, user, comment in finished_images:
- self.cursor.execute("""SELECT wiki, namespace, page_title
- FROM %s WHERE img = %%s AND status <> 'ok'""" %
- self.config['log_table'], (old_image, ))
- not_ok = [(wiki, namespace, page_title.decode('utf-8', 'ignore'))
- for wiki, namespace, page_title in self.cursor]
-
- if not comment: comment = ''
-
- self.reporters.append((old_image.decode('utf-8', 'ignore'),
- new_image.decode('utf-8', 'ignore'),
- user.decode('utf-8', 'ignore'),
- comment.decode('utf-8', 'ignore'), not_ok))
-
-
- def start(self):
- while True:
- self.read_replace_log()
- if self.config.get('replacer_report_replacements', False):
- self.read_finished_replacements()
-
- # Replacer should not loop as often as delinker
- time.sleep(self.config['timeout'] * 2)
-
- def allowed_replacement(self, replacement):
- for source, target in self.disallowed_replacements:
- if source.search(replacement.group(1)) and \
- target.search(replacement.group(2)):
- return False
- return True
+ page = data['query']['pages'].values()[0]
+ if 'missing' in page:
+ raise Exception('Missing page!')
+ return page.get('revisions', [])
+
+ def examine_revision_history(self, revisions, replacement, username):
+ for revision in revisions:
+ if replacement.group(0) in revision['*']:
+ db_time = db_timestamp(revision['timestamp'])
+ if db_time < self.first_revision or not self.first_revision:
+ self.first_revision = int(db_time)
+ return (db_time, strip_image(replacement.group(1)),
+ strip_image(replacement.group(2)),
+ revision['user'], replacement.group(3))
+
+ output('Warning! Could not find out who did %s' % \
+ repr(replacement.group(0)), False)
+ return
+
+ def read_finished_replacements(self):
+ self.cursor.execute('START TRANSACTION WITH CONSISTENT SNAPSHOT')
+ self.cursor.execute("""SELECT old_image, new_image, user, comment
FROM
+ %s WHERE status = 'done' AND timestamp >= %i""" %
\
+ (self.config['replacer_table'], self.first_revision))
+ finished_images = list(self.cursor)
+ self.cursor.execute("""UPDATE %s SET status = 'reported'
+ WHERE status = 'done' AND timestamp >= %i""" % \
+ (self.config['replacer_table'], self.first_revision))
+ self.cursor.commit()
+
+ for old_image, new_image, user, comment in finished_images:
+ self.cursor.execute("""SELECT wiki, namespace, page_title
+ FROM %s WHERE img = %%s AND status <>
'ok'""" %
+ self.config['log_table'], (old_image, ))
+ not_ok = [(wiki, namespace, page_title.decode('utf-8',
'ignore'))
+ for wiki, namespace, page_title in self.cursor]
+
+ if not comment: comment = ''
+
+ self.reporters.append((old_image.decode('utf-8', 'ignore'),
+ new_image.decode('utf-8', 'ignore'),
+ user.decode('utf-8', 'ignore'),
+ comment.decode('utf-8', 'ignore'), not_ok))
+
+
+ def start(self):
+ while True:
+ self.read_replace_log()
+ if self.config.get('replacer_report_replacements', False):
+ self.read_finished_replacements()
+
+ # Replacer should not loop as often as delinker
+ time.sleep(self.config['timeout'] * 2)
+
+ def allowed_replacement(self, replacement):
+ for source, target in self.disallowed_replacements:
+ if source.search(replacement.group(1)) and \
+ target.search(replacement.group(2)):
+ return False
+ return True
class Reporter(threadpool.Thread):
- def __init__(self, pool, site, config):
- self.site = wikipedia.getSite(site.lang, site.family,
- site.user, True)
- self.config = config
-
- threadpool.Thread.__init__(self, pool)
-
- def do(self, args):
- try:
- self.report(args)
- except Exception, e:
- output(u'A critical error during reporting has occured!', False)
- output('%s: %s' % (e.__class__.__name__, str(e)), False)
- traceback.print_exc(file = sys.stderr)
- sys.stderr.flush()
- self.exit()
- os.kill(0, signal.SIGTERM)
-
- def report(self, (old_image, new_image, user, comment, not_ok)):
- not_ok_items = []
- for wiki, namespace, page_title in not_ok:
- # Threadsafety?
- site = wikipedia.getSite(*family(wiki))
- namespace_name = site.namespace(namespace)
- if namespace_name:
- namespace_name = namespace_name + u':'
- else:
- namespace_name = u''
-
- if unicode(site) == unicode(self.site):
- if (namespace, page_title) != (6, old_image):
- not_ok_items.append(u'[[:%s%s]]' % \
- (namespace_name, page_title))
- else:
- not_ok_items.append(u'[[:%s:%s%s]]' % (site_prefix(site),
- namespace_name, page_title))
-
- template = u'{{%s|new_image=%s|user=%s|comment=%s|not_ok=%s}}' % \
- (self.config['replacer_report_template'],
- new_image, user, comment,
- self.config.get('replacer_report_seperator', u',
').join(not_ok_items))
- page = wikipedia.Page(self.site, u'Image:' + old_image)
-
- try:
- text = page.get()
- except wikipedia.NoPage:
- output(u'Warning! Unable to report replacement to %s. Page does not exist!' %
old_image)
- return
- except wikipedia.IsRedirectPage:
- output(u'Warning! %s is a redirect; not reporting replacement!' % old_image)
-
- try:
- page.put(u'%s\n%s' % (template, text),
- comment = u'This image has been replaced by ' + new_image)
- except wikipedia.PageNotSaved, e:
- output(u'Warning! Unable to report replacement to %s.' % old_image, False)
- output('%s: %s' % (e.__class__.__name__, str(e)), False)
- except wikipedia.ServerError, e:
- output(u'Warning! Server error while reporting replacement to %s.' %
old_image, False)
- output('%s: %s' % (e.__class__.__name__, str(e)), False)
- return self.report((old_image, new_image, user, comment, not_ok))
- else:
- output(u'Reporting replacement of %s by %s.' % \
- (old_image, new_image))
-
+ def __init__(self, pool, site, config):
+ self.site = wikipedia.getSite(site.lang, site.family,
+ site.user, True)
+ self.config = config
+
+ threadpool.Thread.__init__(self, pool)
+
+ def do(self, args):
+ try:
+ self.report(args)
+ except Exception, e:
+ output(u'A critical error during reporting has occured!', False)
+ output('%s: %s' % (e.__class__.__name__, str(e)), False)
+ traceback.print_exc(file = sys.stderr)
+ sys.stderr.flush()
+ self.exit()
+ os.kill(0, signal.SIGTERM)
+
+ def report(self, (old_image, new_image, user, comment, not_ok)):
+ not_ok_items = []
+ for wiki, namespace, page_title in not_ok:
+ # Threadsafety?
+ site = wikipedia.getSite(*family(wiki))
+ namespace_name = site.namespace(namespace)
+ if namespace_name:
+ namespace_name = namespace_name + u':'
+ else:
+ namespace_name = u''
+
+ if unicode(site) == unicode(self.site):
+ if (namespace, page_title) != (6, old_image):
+ not_ok_items.append(u'[[:%s%s]]' % \
+ (namespace_name, page_title))
+ else:
+ not_ok_items.append(u'[[:%s:%s%s]]' % (site_prefix(site),
+ namespace_name, page_title))
+
+ template = u'{{%s|new_image=%s|user=%s|comment=%s|not_ok=%s}}' % \
+ (self.config['replacer_report_template'],
+ new_image, user, comment,
+ self.config.get('replacer_report_seperator', u',
').join(not_ok_items))
+ page = wikipedia.Page(self.site, u'Image:' + old_image)
+
+ try:
+ text = page.get()
+ except wikipedia.NoPage:
+ output(u'Warning! Unable to report replacement to %s. Page does not
exist!' % old_image)
+ return
+ except wikipedia.IsRedirectPage:
+ output(u'Warning! %s is a redirect; not reporting replacement!' %
old_image)
+
+ try:
+ page.put(u'%s\n%s' % (template, text),
+ comment = u'This image has been replaced by ' + new_image)
+ except wikipedia.PageNotSaved, e:
+ output(u'Warning! Unable to report replacement to %s.' % old_image,
False)
+ output('%s: %s' % (e.__class__.__name__, str(e)), False)
+ except wikipedia.ServerError, e:
+ output(u'Warning! Server error while reporting replacement to %s.' %
old_image, False)
+ output('%s: %s' % (e.__class__.__name__, str(e)), False)
+ return self.report((old_image, new_image, user, comment, not_ok))
+ else:
+ output(u'Reporting replacement of %s by %s.' % \
+ (old_image, new_image))
+
def main():
- global R
-
- import sys, traceback
- wikipedia.handleArgs()
- output(u'Running ' + __version__)
+ global R
+
+ import sys, traceback
+ wikipedia.handleArgs()
+ output(u'Running ' + __version__)
- try:
- try:
- # FIXME: Add support for single-process replacer.
- R = Replacer()
- output(u'This bot runs from: ' + str(R.site))
- R.start()
- except (SystemExit, KeyboardInterrupt):
- raise
- except Exception, e:
- output('A critical error has occured! Aborting!')
- traceback.print_exc(file = sys.stderr)
- finally:
- try:
- R.reporters.exit()
- except:
- pass
- wikipedia.stopme()
-
+ try:
+ try:
+ # FIXME: Add support for single-process replacer.
+ R = Replacer()
+ output(u'This bot runs from: ' + str(R.site))
+ R.start()
+ except (SystemExit, KeyboardInterrupt):
+ raise
+ except Exception, e:
+ output('A critical error has occured! Aborting!')
+ traceback.print_exc(file = sys.stderr)
+ finally:
+ try:
+ R.reporters.exit()
+ except:
+ pass
+ wikipedia.stopme()
+
if __name__ == '__main__': main()
Modified: trunk/pywikipedia/commonsdelinker/plugins/books.py
===================================================================
--- trunk/pywikipedia/commonsdelinker/plugins/books.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/commonsdelinker/plugins/books.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -3,13 +3,13 @@
import re
class FrPhotographie(object):
- hook = 'before_replace'
- def __init__(self, CommonsDelinker):
- self.CommonsDelinker = CommonsDelinker
- def __call__(self, page, summary, image, replacement):
- site = page.site()
- if (site.lang, site.family.name) == ('fr', 'wikibooks') and
replacement.get() is None:
- if page.title().startswith('Photographie/') or
page.title().startswith('Tribologie/'):
- replacement.set('IMG.svg')
- self.CommonsDelinker.output(u'%s Replaced %s by IMG.svg on %s.' % \
- (self, image.get(), replacement.get()))
+ hook = 'before_replace'
+ def __init__(self, CommonsDelinker):
+ self.CommonsDelinker = CommonsDelinker
+ def __call__(self, page, summary, image, replacement):
+ site = page.site()
+ if (site.lang, site.family.name) == ('fr', 'wikibooks') and
replacement.get() is None:
+ if page.title().startswith('Photographie/') or
page.title().startswith('Tribologie/'):
+ replacement.set('IMG.svg')
+ self.CommonsDelinker.output(u'%s Replaced %s by IMG.svg on %s.' %
\
+ (self, image.get(), replacement.get()))
Modified: trunk/pywikipedia/commonsdelinker/plugins/debug.py
===================================================================
--- trunk/pywikipedia/commonsdelinker/plugins/debug.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/commonsdelinker/plugins/debug.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -2,16 +2,16 @@
__version__ = '$Id: $'
class Diff(object):
- hook = 'before_save'
- def __init__(self, CommonsDelinker):
- self.CommonsDelinker = CommonsDelinker
- def __call__(self, page, text, new_text, summary):
- diff = difflib.context_diff(
- text.encode('utf-8').splitlines(True),
- new_text.get().encode('utf-8').splitlines(True))
-
- f = open((u'diff/%s-%s-%s.txt' % (page.urlname().replace('/',
'-'),
- page.site().dbName(), page.editTime())).encode('utf-8', 'ignore'),
'w')
-
- f.writelines(diff)
- f.close()
\ No newline at end of file
+ hook = 'before_save'
+ def __init__(self, CommonsDelinker):
+ self.CommonsDelinker = CommonsDelinker
+ def __call__(self, page, text, new_text, summary):
+ diff = difflib.context_diff(
+ text.encode('utf-8').splitlines(True),
+ new_text.get().encode('utf-8').splitlines(True))
+
+ f = open((u'diff/%s-%s-%s.txt' % (page.urlname().replace('/',
'-'),
+ page.site().dbName(), page.editTime())).encode('utf-8',
'ignore'), 'w')
+
+ f.writelines(diff)
+ f.close()
\ No newline at end of file
Modified: trunk/pywikipedia/commonsdelinker/plugins/flags.py
===================================================================
--- trunk/pywikipedia/commonsdelinker/plugins/flags.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/commonsdelinker/plugins/flags.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -3,30 +3,30 @@
import re
class NlWiki(object):
- hook = 'gallery_replace'
- def __init__(self, CommonsDelinker):
- self.CommonsDelinker = CommonsDelinker
- def __call__(self, page, summary, image, replacement, match, groups):
- site = page.site()
- if (site.lang, site.family.name) == ('nl', 'wikipedia') and
replacement.get() is None:
- commands = self.CommonsDelinker.SummaryCache.get(site, 'Vlaggen', default =
'')
-
- flags = re.findall(r'(?s)\<\!\-\-begin\-flags
(.*?)\-\-\>(.*?)\<\!\-\-end\-flags\-\-\>', commands)
- text = page.get()
-
- namespace = site.namespace(14)
- r_namespace = r'(?:[Cc]ategory)|(?:[%s%s]%s)' % \
- (namespace[0], namespace[0].lower(), namespace[1:])
-
- for new_image, categories in flags:
- for category in categories.split('\n'):
- if category.strip() == '': continue
-
- r_cat = r'\[\[\s*%s\s*\:\s*%s\s*(?:\|.*?)?\s*\]\]' % (r_namespace,
- re.sub(r'\\[ _]', '[ _]', re.escape(category.strip())))
- if re.search(r_cat, text):
- self.CommonsDelinker.output(
- u'%s %s replaced by %s in category %s' % \
- (self, image, new_image, category))
- replacement.set(new_image.replace(' ', '_'))
-
\ No newline at end of file
+ hook = 'gallery_replace'
+ def __init__(self, CommonsDelinker):
+ self.CommonsDelinker = CommonsDelinker
+ def __call__(self, page, summary, image, replacement, match, groups):
+ site = page.site()
+ if (site.lang, site.family.name) == ('nl', 'wikipedia') and
replacement.get() is None:
+ commands = self.CommonsDelinker.SummaryCache.get(site, 'Vlaggen',
default = '')
+
+ flags = re.findall(r'(?s)\<\!\-\-begin\-flags
(.*?)\-\-\>(.*?)\<\!\-\-end\-flags\-\-\>', commands)
+ text = page.get()
+
+ namespace = site.namespace(14)
+ r_namespace = r'(?:[Cc]ategory)|(?:[%s%s]%s)' % \
+ (namespace[0], namespace[0].lower(), namespace[1:])
+
+ for new_image, categories in flags:
+ for category in categories.split('\n'):
+ if category.strip() == '': continue
+
+ r_cat = r'\[\[\s*%s\s*\:\s*%s\s*(?:\|.*?)?\s*\]\]' %
(r_namespace,
+ re.sub(r'\\[ _]', '[ _]',
re.escape(category.strip())))
+ if re.search(r_cat, text):
+ self.CommonsDelinker.output(
+ u'%s %s replaced by %s in category %s' % \
+ (self, image, new_image, category))
+ replacement.set(new_image.replace(' ', '_'))
+
\ No newline at end of file
Modified: trunk/pywikipedia/commonsdelinker/plugins/skipped_pages.py
===================================================================
--- trunk/pywikipedia/commonsdelinker/plugins/skipped_pages.py 2009-03-24 01:15:12 UTC
(rev 6539)
+++ trunk/pywikipedia/commonsdelinker/plugins/skipped_pages.py 2009-03-24 01:15:50 UTC
(rev 6540)
@@ -1,12 +1,12 @@
__version__ = '$Id: $'
class SkipPages(object):
- hook = 'before_save'
- def __init__(self, CommonsDelinker):
- self.CommonsDelinker = CommonsDelinker
- def __call__(self, page, text, new_text, summary):
- site = page.site()
- if (site.lang, site.family.name) == ('en', 'wikipedia'):
- if page.title == 'Wikipedia:Sound/list':
- return False
- return True
\ No newline at end of file
+ hook = 'before_save'
+ def __init__(self, CommonsDelinker):
+ self.CommonsDelinker = CommonsDelinker
+ def __call__(self, page, text, new_text, summary):
+ site = page.site()
+ if (site.lang, site.family.name) == ('en', 'wikipedia'):
+ if page.title == 'Wikipedia:Sound/list':
+ return False
+ return True
\ No newline at end of file
Modified: trunk/pywikipedia/commonsdelinker/threadpool.py
===================================================================
--- trunk/pywikipedia/commonsdelinker/threadpool.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/commonsdelinker/threadpool.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -28,156 +28,156 @@
import sys, threading, os
class ThreadPool(dict):
- pools = []
- def __init__(self, worker, max_threads, *args, **kwargs):
- dict.__init__(self)
+ pools = []
+ def __init__(self, worker, max_threads, *args, **kwargs):
+ dict.__init__(self)
- self.jobLock = threading.Lock()
- self.jobQueue = []
- self.worker = worker
- self.threads = []
-
- self.max_threads = max_threads
- self.args = args
- self.kwargs = kwargs
+ self.jobLock = threading.Lock()
+ self.jobQueue = []
+ self.worker = worker
+ self.threads = []
+
+ self.max_threads = max_threads
+ self.args = args
+ self.kwargs = kwargs
- self.pools.append(self)
+ self.pools.append(self)
- def append(self, job):
- self.jobLock.acquire()
- counter = 0
- try:
- self.jobQueue.append(job)
- # The amount of workers needed to be unlocked
- unlock_workers = len(self.jobQueue)
-
- for event in self.itervalues():
- if not event.isSet():
- event.set()
- counter += 1
- if counter == unlock_workers:
- break
- finally:
- self.jobLock.release()
- if counter == 0 and len(self.threads) < self.max_threads:
- self.add_thread()
- self.start()
-
- def add_thread(self):
- self.jobLock.acquire()
- try:
- thread = self.worker(self, *self.args, **self.kwargs)
- self.threads.append(thread)
- self[id(thread)] = threading.Event()
- finally:
- self.jobLock.release()
-
- def start(self):
- for thread in self.threads:
- if not thread.isAlive():
- thread.start()
- def exit(self):
- self.jobLock.acquire()
- try:
- del self.jobQueue[:]
- for thread in self.threads:
- thread.quit = True
- self[id(thread)].set()
- finally:
- self.jobLock.release()
+ def append(self, job):
+ self.jobLock.acquire()
+ counter = 0
+ try:
+ self.jobQueue.append(job)
+ # The amount of workers needed to be unlocked
+ unlock_workers = len(self.jobQueue)
+
+ for event in self.itervalues():
+ if not event.isSet():
+ event.set()
+ counter += 1
+ if counter == unlock_workers:
+ break
+ finally:
+ self.jobLock.release()
+ if counter == 0 and len(self.threads) < self.max_threads:
+ self.add_thread()
+ self.start()
+
+ def add_thread(self):
+ self.jobLock.acquire()
+ try:
+ thread = self.worker(self, *self.args, **self.kwargs)
+ self.threads.append(thread)
+ self[id(thread)] = threading.Event()
+ finally:
+ self.jobLock.release()
+
+ def start(self):
+ for thread in self.threads:
+ if not thread.isAlive():
+ thread.start()
+ def exit(self):
+ self.jobLock.acquire()
+ try:
+ del self.jobQueue[:]
+ for thread in self.threads:
+ thread.quit = True
+ self[id(thread)].set()
+ finally:
+ self.jobLock.release()
class Thread(threading.Thread):
- timeout = None
- def __init__(self, pool):
- threading.Thread.__init__(self)
- self.pool = pool
- self.quit = False
-
- def run(self):
- while True:
- # No try..finally: lock.release() here:
- # The lock might be released twice, in case
- # the thread waits for an event, a race
- # condition might occur where a lock is released
- # that is acquired by another thread.
- self.pool.jobLock.acquire()
-
- if self.quit and not self.pool.jobQueue:
- # Only return once the jobQueue is empty.
- self.pool.jobLock.release()
- return
-
- if not self.pool.jobQueue:
- # In case no job is available, wait for the pool
- # to call and do not start a busy while loop.
- event = self.pool[id(self)]
- self.pool.jobLock.release()
- event.clear()
- event.wait(self.timeout)
- if not event.isSet() and self.timeout != None:
- if self.starve(): return
- continue
- job = self.pool.jobQueue.pop(0)
- self.pool.jobLock.release()
-
- self.do(job)
-
- def exit(self):
- self.pool.jobLock.acquire()
- try:
- self.quit = True
- if id(self) in self.pool:
- self.pool[id(self)].set()
- del self.pool[id(self)]
- if self in self.pool.threads:
- self.pool.threads.remove(self)
- finally:
- self.pool.jobLock.release()
-
- def starve(self):
- pass
+ timeout = None
+ def __init__(self, pool):
+ threading.Thread.__init__(self)
+ self.pool = pool
+ self.quit = False
+
+ def run(self):
+ while True:
+ # No try..finally: lock.release() here:
+ # The lock might be released twice, in case
+ # the thread waits for an event, a race
+ # condition might occur where a lock is released
+ # that is acquired by another thread.
+ self.pool.jobLock.acquire()
+
+ if self.quit and not self.pool.jobQueue:
+ # Only return once the jobQueue is empty.
+ self.pool.jobLock.release()
+ return
+
+ if not self.pool.jobQueue:
+ # In case no job is available, wait for the pool
+ # to call and do not start a busy while loop.
+ event = self.pool[id(self)]
+ self.pool.jobLock.release()
+ event.clear()
+ event.wait(self.timeout)
+ if not event.isSet() and self.timeout != None:
+ if self.starve(): return
+ continue
+ job = self.pool.jobQueue.pop(0)
+ self.pool.jobLock.release()
+
+ self.do(job)
+
+ def exit(self):
+ self.pool.jobLock.acquire()
+ try:
+ self.quit = True
+ if id(self) in self.pool:
+ self.pool[id(self)].set()
+ del self.pool[id(self)]
+ if self in self.pool.threads:
+ self.pool.threads.remove(self)
+ finally:
+ self.pool.jobLock.release()
+
+ def starve(self):
+ pass
def catch_signals():
- import signal
- signal.signal(signal.SIGINT, sig_handler)
- signal.signal(signal.SIGTERM, sig_handler)
+ import signal
+ signal.signal(signal.SIGINT, sig_handler)
+ signal.signal(signal.SIGTERM, sig_handler)
def sig_handler(signalnum, stack):
- import signal
- for pool in ThreadPool.pools:
- pool.exit()
-
- if signalnum == signal.SIGINT:
- raise KeyboardInterrupt
- if signalnum == signal.SIGTERM:
- raise SystemExit
-
+ import signal
+ for pool in ThreadPool.pools:
+ pool.exit()
+
+ if signalnum == signal.SIGINT:
+ raise KeyboardInterrupt
+ if signalnum == signal.SIGTERM:
+ raise SystemExit
+
def terminate():
- # Maybe not a good idea, will also kill child processes
- import signal
- os.kill(0, signal.SIGTERM)
+ # Maybe not a good idea, will also kill child processes
+ import signal
+ os.kill(0, signal.SIGTERM)
if __name__ == '__main__':
- import time
- # Test cases
-
- class Worker(Thread):
- def do(self, args):
- print 'Working', self
- time.sleep(10)
- print 'Done', self
-
- pool = ThreadPool(Worker)
- print 'Spawning 5 threads'
- [pool.add_thread() for i in xrange(5)]
- pool.start()
-
- print 'Doing 25 jobs'
- for i in xrange(25):
- print 'Job', i
- pool.append(i)
- time.sleep(i % 6)
-
- for thread in pool.threads:
- thread.exit()
+ import time
+ # Test cases
+
+ class Worker(Thread):
+ def do(self, args):
+ print 'Working', self
+ time.sleep(10)
+ print 'Done', self
+
+ pool = ThreadPool(Worker)
+ print 'Spawning 5 threads'
+ [pool.add_thread() for i in xrange(5)]
+ pool.start()
+
+ print 'Doing 25 jobs'
+ for i in xrange(25):
+ print 'Job', i
+ pool.append(i)
+ time.sleep(i % 6)
+
+ for thread in pool.threads:
+ thread.exit()
Modified: trunk/pywikipedia/config.py
===================================================================
--- trunk/pywikipedia/config.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/config.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -64,7 +64,7 @@
authenticate = {}
#
-# Security Connection for Wikimedia Projects
+# Security Connection for Wikimedia Projects
#
#
#
Modified: trunk/pywikipedia/copyright.py
===================================================================
--- trunk/pywikipedia/copyright.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/copyright.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -1029,9 +1029,9 @@
wikipedia.output(u'Page %s is a disambiguation page' %
page.aslink())
continue
- wikipedia.output(page.title())
+ wikipedia.output(page.title())
- if original_text:
+ if original_text:
text = skip_section(original_text)
if remove_wikicode_dotall:
Modified: trunk/pywikipedia/copyright_put.py
===================================================================
--- trunk/pywikipedia/copyright_put.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/copyright_put.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -39,7 +39,7 @@
stat_msg = {
'en': [u'Statistics', u'Page', u'Entries',
u'Size', u'Total', 'Update'],
- 'ar': [u'إحصاءات', u'صفحة', u'مدخلات', u'حجم',
u'إجمالي', 'تحديث'],
+ 'ar': [u'إحصاءات', u'صفحة', u'مدخلات',
u'حجم', u'إجمالي', 'تحديث'],
'it': [u'Statistiche', u'Pagina', u'Segnalazioni',
u'Lunghezza', u'Totale', u'Ultimo aggiornamento'],
}
Modified: trunk/pywikipedia/date.py
===================================================================
--- trunk/pywikipedia/date.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/date.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -782,7 +782,7 @@
(lambda v: dh_constVal( v, 1, u'1-9'),
lambda p: p == 1),
(lambda v: dh( v, u'%d-%d', lambda i: (encDec0(i),encDec0(i)+9),
decSinglVal ), alwaysTrue)]),
- 'nn' : lambda v: dh_decAD( v, u'%d0-åra' ), # FIXME: not
sure of this one
+ 'nn' : lambda v: dh_decAD( v, u'%d0-åra' ), # FIXME: not
sure of this one
'no' : lambda v: dh_decAD( v, u'%d-årene' ),
'os' : lambda v: dh_decAD( v, u'%d-тæ' ),
@@ -998,33 +998,33 @@
'CenturyBC': {
'af' : lambda m: multi( m, [
- (lambda v: dh_centuryBC( v, u'%dste eeu v.C.' ), lambda p: p
in [1,8] or (p >= 20)),
- (lambda v: dh_centuryBC( v, u'%dde eeu v.C.' ),
alwaysTrue)]),
+ (lambda v: dh_centuryBC( v, u'%dste eeu v.C.' ), lambda p:
p in [1,8] or (p >= 20)),
+ (lambda v: dh_centuryBC( v, u'%dde eeu v.C.' ),
alwaysTrue)]),
'bg' : lambda v: dh_centuryBC( v, u'%d век пр.н.е.' ),
- 'br' : lambda m: multi( m, [
- (lambda v: dh_constVal( v, 1, u'Iañ kantved kt JK'), lambda p:
p == 1),
- (lambda v: dh_constVal( v, 2, u'Eil kantved kt JK'), lambda p:
p == 2),
- (lambda v: dh_centuryBC( v, u'%Re kantved kt JK'), lambda p:
p in [2,3]),
- (lambda v: dh_centuryBC( v, u'%Rvet kantved kt JK'),
alwaysTrue)]),
+ 'br' : lambda m: multi( m, [
+ (lambda v: dh_constVal( v, 1, u'Iañ kantved kt JK'), lambda
p: p == 1),
+ (lambda v: dh_constVal( v, 2, u'Eil kantved kt JK'), lambda
p: p == 2),
+ (lambda v: dh_centuryBC( v, u'%Re kantved kt JK'), lambda
p: p in [2,3]),
+ (lambda v: dh_centuryBC( v, u'%Rvet kantved kt JK'),
alwaysTrue)]),
'ca' : lambda v: dh_centuryBC( v, u'Segle %R aC' ),
'cs' : lambda v: dh_centuryBC( v, u'%d. století př. n. l.'
),
'da' : lambda v: dh_centuryBC( v, u'%d. århundrede f.Kr.'
),
'de' : lambda v: dh_centuryBC( v, u'%d. Jahrhundert v. Chr.'
),
'el' : lambda v: dh_centuryBC( v, u'%dος αιώνας π.Χ.' ),
'en' : lambda m: multi( m, [
- (lambda v: dh_centuryBC( v, u'%dst century BC' ), lambda p:
p == 1 or (p > 20 and p%10 == 1)),
- (lambda v: dh_centuryBC( v, u'%dnd century BC' ), lambda p: p
== 2 or (p > 20 and p%10 == 2)),
- (lambda v: dh_centuryBC( v, u'%drd century BC' ), lambda p:
p == 3 or (p > 20 and p%10 == 3)),
- (lambda v: dh_centuryBC( v, u'%dth century BC' ),
alwaysTrue)]),
+ (lambda v: dh_centuryBC( v, u'%dst century BC' ), lambda
p: p == 1 or (p > 20 and p%10 == 1)),
+ (lambda v: dh_centuryBC( v, u'%dnd century BC' ), lambda
p: p == 2 or (p > 20 and p%10 == 2)),
+ (lambda v: dh_centuryBC( v, u'%drd century BC' ), lambda
p: p == 3 or (p > 20 and p%10 == 3)),
+ (lambda v: dh_centuryBC( v, u'%dth century BC' ),
alwaysTrue)]),
'eo' : lambda v: dh_centuryBC( v, u'%d-a jarcento a.K.' ),
'es' : lambda v: dh_centuryBC( v, u'Siglo %R adC' ),
'et' : lambda v: dh_centuryBC( v, u'%d. aastatuhat eKr' ),
'fi' : lambda m: multi( m, [
- (lambda v: dh_constVal( v, 1, u'Ensimmäinen vuosisata
eaa.'), lambda p: p == 1),
+ (lambda v: dh_constVal( v, 1, u'Ensimmäinen vuosisata eaa.'),
lambda p: p == 1),
(lambda v: dh( v, u'%d00-luku eaa.', lambda i: i-1, lambda ii:
ii[0]+1 ), alwaysTrue)]),
'fr' : lambda m: multi( m, [
- (lambda v: dh_centuryBC( v, u'%Rer siècle av. J.-C.' ), lambda
p: p == 1),
- (lambda v: dh_centuryBC( v, u'%Re siècle av. J.-C.' ),
alwaysTrue)]),
+ (lambda v: dh_centuryBC( v, u'%Rer siècle av. J.-C.' ),
lambda p: p == 1),
+ (lambda v: dh_centuryBC( v, u'%Re siècle av. J.-C.' ),
alwaysTrue)]),
'he' : lambda v: dh_centuryBC( v, u'המאה ה־%d לפני הספירה'
),
'hr' : lambda v: dh_centuryBC( v, u'%d. stoljeće p.n.e.' ),
'id' : lambda v: dh_centuryBC( v, u'Abad ke-%d SM' ),
@@ -1361,7 +1361,7 @@
addFmt2('sv', False, u"%%d %s", False )
addFmt2('ta', False, u"%s %%d" )
addFmt2('te', False, u"%s %%d" )
-addFmt2('th', False, u"%%d %s" ) # %%T
+addFmt2('th', False, u"%%d %s" ) # %%T
addFmt2('tl', False, u"%s %%d" )
addFmt2('tr', False, u"%%d %s", True )
addFmt2('tt', False, u"%%d. %s", True )
@@ -1442,21 +1442,21 @@
# In addition, tuple contains start, end, and step values that will be used to test the
formats table for internal consistency.
#
formatLimits = {
- 'MonthName' : (lambda v: 1<=v and v<13, 1,13),
- 'Number' : (lambda v: 0<=v and v<1000000, 0,1001),
+ 'MonthName' : (lambda v: 1<=v and v<13,
1,13),
+ 'Number' : (lambda v: 0<=v and v<1000000,
0,1001),
- 'YearAD' : (lambda v: 0<=v and v<2501, 0,2501),
- 'YearBC' : (lambda v: 0<=v and v<4001, 0,501), # zh:
has years as old as 前1700年
- 'DecadeAD' : (lambda v: 0<=v and v<2501, 0,2501), # At
some point need to re-add "and v%10==0" to the limitation
- 'DecadeBC' : (lambda v: 0<=v and v<4001, 0,501), #
zh: has decades as old as 前1700年代
- 'CenturyAD' : (lambda v: 1<=v and v<41, 1,23), #
Some centuries use Roman numerals or a given list - do not exceed them in testing
- 'CenturyBC' : (lambda v: 1<=v and v<91, 1,23), #
Some centuries use Roman numerals or a given list - do not exceed them in testing
- 'MillenniumAD' : (lambda v: 1<=v and v<6, 1,4), #
For milleniums, only test first 3 AD Milleniums,
- 'MillenniumBC' : (lambda v: 1<=v and v<20, 1,2), #
And only 1 BC Millenium
+ 'YearAD' : (lambda v: 0<=v and v<2501,
0,2501),
+ 'YearBC' : (lambda v: 0<=v and v<4001, 0,501),
# zh: has years as old as 前1700年
+ 'DecadeAD' : (lambda v: 0<=v and v<2501,
0,2501), # At some point need to re-add "and v%10==0" to the limitation
+ 'DecadeBC' : (lambda v: 0<=v and v<4001,
0,501), # zh: has decades as old as 前1700年代
+ 'CenturyAD' : (lambda v: 1<=v and v<41,
1,23), # Some centuries use Roman numerals or a given list - do not exceed them in
testing
+ 'CenturyBC' : (lambda v: 1<=v and v<91,
1,23), # Some centuries use Roman numerals or a given list - do not exceed them in
testing
+ 'MillenniumAD' : (lambda v: 1<=v and v<6, 1,4),
# For milleniums, only test first 3 AD Milleniums,
+ 'MillenniumBC' : (lambda v: 1<=v and v<20, 1,2),
# And only 1 BC Millenium
'CenturyAD_Cat' : (lambda v: 1<=v and v<41, 1,23),
# Some centuries use Roman numerals or a given list - do not exceed them in testing
'CenturyBC_Cat' : (lambda v: 1<=v and v<41, 1,23),
# Some centuries use Roman numerals or a given list - do not exceed them in testing
- 'Cat_Year_MusicAlbums' : (lambda v: 1950<=v and v<2021,
1950,2021),
- 'CurrEvents' : (lambda v: 0<=v and v<1, 0,1),
+ 'Cat_Year_MusicAlbums' : (lambda v: 1950<=v and v<2021,
1950,2021),
+ 'CurrEvents' : (lambda v: 0<=v and v<1, 0,1),
}
# All month of year articles are in the same format
Modified: trunk/pywikipedia/delinker.py
===================================================================
--- trunk/pywikipedia/delinker.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/delinker.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -9,9 +9,9 @@
module = 'delinker'
if len(sys.argv) > 1:
- if sys.argv[1] == 'replacer':
- del sys.argv[1]
- module = 'image_replacer'
+ if sys.argv[1] == 'replacer':
+ del sys.argv[1]
+ module = 'image_replacer'
bot = __import__(module)
bot.main()
\ No newline at end of file
Modified: trunk/pywikipedia/djvutext.py
===================================================================
--- trunk/pywikipedia/djvutext.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/djvutext.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -92,7 +92,7 @@
self.prefix = self.prefix[6:]
wikipedia.output(u"Using prefix %s" % self.prefix)
gen = self.PagesGenerator()
-
+
site = wikipedia.getSite()
self.username = config.usernames[site.family.name][site.lang]
@@ -109,7 +109,7 @@
s = f.read()
f.close()
return s.find('TXTz') >= 0
-
+
def get_page(self, pageno):
wikipedia.output(unicode("fetching page %d" % (pageno)))
cmd = u"djvutxt -page=%d \"%s\" \"%s.out\"" %
(pageno, self.djvu, self.djvu)
@@ -142,7 +142,7 @@
# only save if something was changed
# automatically ask if overwriting an existing page
-
+
ask = self.ask
if exists:
ask = True
Modified: trunk/pywikipedia/families/anarchopedia_family.py
===================================================================
--- trunk/pywikipedia/families/anarchopedia_family.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/families/anarchopedia_family.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -84,7 +84,7 @@
'id': u'Pembicaraan Anarchopedia',
'it': u'Discussioni Anarchopedia',
'ja': u'アナーキォペディア‐ノート' ,
- 'no': u'Anarchopedia-diskusjon' ,
+ 'no': u'Anarchopedia-diskusjon' ,
'sh': u'Разговор о Anarhopedija / Анархопедија',
'or': u'Anarchopedia-diskusjon',
'pl': u'Dyskusja Anarchopedia',
Modified: trunk/pywikipedia/families/battlestarwiki_family.py
===================================================================
--- trunk/pywikipedia/families/battlestarwiki_family.py 2009-03-24 01:15:12 UTC (rev
6539)
+++ trunk/pywikipedia/families/battlestarwiki_family.py 2009-03-24 01:15:50 UTC (rev
6540)
@@ -19,7 +19,7 @@
}
# Most namespaces are inherited from family.
-
+
self.namespaces[4] = {
'_default': u'Battlestar Wiki',
}
@@ -47,7 +47,7 @@
# if you carefully avoid the options, you could get away without these
# for another wiki family.
self.languages_by_size = ['en', 'de']
-
+
alphabetic = ['de', 'en', 'es', 'fr',
'tr', 'zh']
def hostname(self,code):
Modified: trunk/pywikipedia/families/memoryalpha_family.py
===================================================================
--- trunk/pywikipedia/families/memoryalpha_family.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/families/memoryalpha_family.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -39,12 +39,12 @@
'sv': u'Memory Alphadiskussion',
}
self.namespaces[100] = {
- '_default': u'Forum',
- }
+ '_default': u'Forum',
+ }
self.namespaces[101] = {
- '_default': u'Forum talk',
- 'de': u'Forum Diskussion',
- }
+ '_default': u'Forum talk',
+ 'de': u'Forum Diskussion',
+ }
# A few selected big languages for things that we do not want to loop over
# all languages. This is only needed by the titletranslate.py module, so
Modified: trunk/pywikipedia/families/uncyclopedia_family.py
===================================================================
--- trunk/pywikipedia/families/uncyclopedia_family.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/families/uncyclopedia_family.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -16,755 +16,755 @@
class Family(family.Family):
def __init__(self):
- family.Family.__init__(self)
- self.name = 'uncyclopedia'
+ family.Family.__init__(self)
+ self.name = 'uncyclopedia'
- self.langs = {
- 'ar': 'beidipedia.wikia.com',
- 'ast':'nunyepedia.wikia.com',
- 'bn': 'bn.uncyc.org',
- 'bg': 'bg.oxypedia.net',
- 'bs': 'bs.neciklopedija.org',
- 'ca': 'valenciclopedia.wikia.com',
- 'common': 'commons.uncyclomedia.org',
- 'cs': 'necyklopedie.wikia.com',
- 'cy': 'cy.uncyclopedia.org.uk',
- 'da': 'spademanns.wikia.com',
- 'de': 'de.uncyclopedia.org',
- 'el': 'frikipaideia.wikia.com',
- 'en': 'uncyclopedia.org',
- 'eo': 'neciklopedio.wikia.com',
- 'es': 'inciclopedia.wikia.com',
- 'et': 'ebatsuklopeedia.org',
- 'fa': 'fa.uncyc.org',
- 'fi': 'hikipedia.info',
- 'fr': 'desencyclopedie.wikia.com',
- 'got':'unsaiklopedia.org',
- 'he': 'eincyclopedia.wikia.com',
- 'hr': 'hr.neciklopedija.org',
- 'hu': 'unciklopedia.org',
- 'id': 'tolololpedia.wikia.com',
- 'info': 'uncyclopedia.info',
- 'it': 'nonciclopedia.wikia.com',
- 'ja': 'ansaikuropedia.org',
- 'jv': 'ndhablek.wikia.com',
- 'ko': 'uncyclopedia.kr',
- 'la': 'uncapaedia.wikia.com',
- 'lb': 'kengencyclopedia.org',
- 'lt': 'juokopedija.org',
- 'lv': 'lv.neciklopedija.org',
- 'meta': 'meta.uncyclomedia.org',
- 'mg': 'hatsiklopedia.org',
- 'mk': 'mk.neciklopedija.org',
- 'nl': 'oncyclopedia.net',
- 'nn': 'ikkepedia.org',
- 'no': 'ikkepedia.org',
- 'pl': 'nonsensopedia.wikia.com',
- 'pt': 'desciclopedia.ws',
- 'ro': 'uncyclopedia.ro',
- 'ru': 'absurdopedia.wikia.com',
- 'sk': 'necyklopedia.wikia.com',
- 'sl': 'butalopedija.org',
- 'sr': 'sr.neciklopedija.org',
- 'su': 'su.goblogpedia.wikia.com',
- 'sv': 'psyklopedin.org',
- 'th': 'th.uncyclopedia.info',
- 'tr': 'yansiklopedi.org',
- 'uk': 'inciklopedia.org',
- 'yi': 'keinziklopedie.wikia.com',
- 'zh-hk': 'uncyclopedia.hk',
- 'zh-tw':'uncyclopedia.tw',
- 'zh': 'zh.uncyclopedia.wikia.com',
- }
+ self.langs = {
+ 'ar': 'beidipedia.wikia.com',
+ 'ast':'nunyepedia.wikia.com',
+ 'bn': 'bn.uncyc.org',
+ 'bg': 'bg.oxypedia.net',
+ 'bs': 'bs.neciklopedija.org',
+ 'ca': 'valenciclopedia.wikia.com',
+ 'common': 'commons.uncyclomedia.org',
+ 'cs': 'necyklopedie.wikia.com',
+ 'cy': 'cy.uncyclopedia.org.uk',
+ 'da': 'spademanns.wikia.com',
+ 'de': 'de.uncyclopedia.org',
+ 'el': 'frikipaideia.wikia.com',
+ 'en': 'uncyclopedia.org',
+ 'eo': 'neciklopedio.wikia.com',
+ 'es': 'inciclopedia.wikia.com',
+ 'et': 'ebatsuklopeedia.org',
+ 'fa': 'fa.uncyc.org',
+ 'fi': 'hikipedia.info',
+ 'fr': 'desencyclopedie.wikia.com',
+ 'got':'unsaiklopedia.org',
+ 'he': 'eincyclopedia.wikia.com',
+ 'hr': 'hr.neciklopedija.org',
+ 'hu': 'unciklopedia.org',
+ 'id': 'tolololpedia.wikia.com',
+ 'info': 'uncyclopedia.info',
+ 'it': 'nonciclopedia.wikia.com',
+ 'ja': 'ansaikuropedia.org',
+ 'jv': 'ndhablek.wikia.com',
+ 'ko': 'uncyclopedia.kr',
+ 'la': 'uncapaedia.wikia.com',
+ 'lb': 'kengencyclopedia.org',
+ 'lt': 'juokopedija.org',
+ 'lv': 'lv.neciklopedija.org',
+ 'meta': 'meta.uncyclomedia.org',
+ 'mg': 'hatsiklopedia.org',
+ 'mk': 'mk.neciklopedija.org',
+ 'nl': 'oncyclopedia.net',
+ 'nn': 'ikkepedia.org',
+ 'no': 'ikkepedia.org',
+ 'pl': 'nonsensopedia.wikia.com',
+ 'pt': 'desciclopedia.ws',
+ 'ro': 'uncyclopedia.ro',
+ 'ru': 'absurdopedia.wikia.com',
+ 'sk': 'necyklopedia.wikia.com',
+ 'sl': 'butalopedija.org',
+ 'sr': 'sr.neciklopedija.org',
+ 'su': 'su.goblogpedia.wikia.com',
+ 'sv': 'psyklopedin.org',
+ 'th': 'th.uncyclopedia.info',
+ 'tr': 'yansiklopedi.org',
+ 'uk': 'inciklopedia.org',
+ 'yi': 'keinziklopedie.wikia.com',
+ 'zh-hk': 'uncyclopedia.hk',
+ 'zh-tw':'uncyclopedia.tw',
+ 'zh': 'zh.uncyclopedia.wikia.com',
+ }
- #
- # project namespaces & custom namespace lists
- #
+ #
+ # project namespaces & custom namespace lists
+ #
- self.namespaces[-2]['ar'] = u'ملف'
- self.namespaces[-2]['bs'] = u'Medija'
- self.namespaces[-2]['he'] = u'מדיה'
- self.namespaces[-2]['hu'] = u'Media'
- self.namespaces[-2]['th'] = u'สื่อ'
- self.namespaces[-2]['zh-hk'] = u'媒體'
- self.namespaces[-2]['zh-tw'] = u'媒體'
+ self.namespaces[-2]['ar'] = u'ملف'
+ self.namespaces[-2]['bs'] = u'Medija'
+ self.namespaces[-2]['he'] = u'מדיה'
+ self.namespaces[-2]['hu'] = u'Media'
+ self.namespaces[-2]['th'] = u'สื่อ'
+ self.namespaces[-2]['zh-hk'] = u'媒體'
+ self.namespaces[-2]['zh-tw'] = u'媒體'
- self.namespaces[-1]['bs'] = u'Posebno'
- self.namespaces[-1]['ja'] = u'Special'
- self.namespaces[-1]['jv'] = u'Astamiwa'
- self.namespaces[-1]['lb'] = u'Spezial'
- self.namespaces[-1]['zh-hk'] = u'特殊'
- self.namespaces[-1]['zh-tw'] = u'特殊'
+ self.namespaces[-1]['bs'] = u'Posebno'
+ self.namespaces[-1]['ja'] = u'Special'
+ self.namespaces[-1]['jv'] = u'Astamiwa'
+ self.namespaces[-1]['lb'] = u'Spezial'
+ self.namespaces[-1]['zh-hk'] = u'特殊'
+ self.namespaces[-1]['zh-tw'] = u'特殊'
- self.namespaces[1]['ast'] = u'Discusión'
- self.namespaces[1]['bs'] = u'Razgovor'
- self.namespaces[1]['id'] = u'Pembicaraan'
- self.namespaces[1]['ja'] = u'Talk'
- self.namespaces[1]['jv'] = u'Dhiskusi'
- self.namespaces[1]['lb'] = u'Diskussioun'
- self.namespaces[1]['lv'] = u'Diskusija'
- self.namespaces[1]['mg'] = u'Discuter'
- self.namespaces[1]['th'] = u'พูดคุย'
- self.namespaces[1]['zh-hk'] = u'討論'
- self.namespaces[1]['zh-tw'] = u'討論'
+ self.namespaces[1]['ast'] = u'Discusión'
+ self.namespaces[1]['bs'] = u'Razgovor'
+ self.namespaces[1]['id'] = u'Pembicaraan'
+ self.namespaces[1]['ja'] = u'Talk'
+ self.namespaces[1]['jv'] = u'Dhiskusi'
+ self.namespaces[1]['lb'] = u'Diskussioun'
+ self.namespaces[1]['lv'] = u'Diskusija'
+ self.namespaces[1]['mg'] = u'Discuter'
+ self.namespaces[1]['th'] = u'พูดคุย'
+ self.namespaces[1]['zh-hk'] = u'討論'
+ self.namespaces[1]['zh-tw'] = u'討論'
- self.namespaces[2]['bs'] = u'Korisnik'
- self.namespaces[2]['jv'] = u'Panganggo'
- self.namespaces[2]['lb'] = u'Benotzer'
- self.namespaces[2]['lv'] = u'Lietotājs'
- self.namespaces[2]['mg'] = u'Utilisateur'
- self.namespaces[2]['pl'] = u'Użytkownik'
- self.namespaces[2]['zh-hk'] = u'用戶'
- self.namespaces[2]['zh-tw'] = u'用戶'
+ self.namespaces[2]['bs'] = u'Korisnik'
+ self.namespaces[2]['jv'] = u'Panganggo'
+ self.namespaces[2]['lb'] = u'Benotzer'
+ self.namespaces[2]['lv'] = u'Lietotājs'
+ self.namespaces[2]['mg'] = u'Utilisateur'
+ self.namespaces[2]['pl'] = u'Użytkownik'
+ self.namespaces[2]['zh-hk'] = u'用戶'
+ self.namespaces[2]['zh-tw'] = u'用戶'
- self.namespaces[3]['ast'] = u'Usuariu discusión'
- self.namespaces[3]['bs'] = u'Razgovor sa korisnikom'
- self.namespaces[3]['da'] = u'Brugerdiskussion'
- self.namespaces[3]['hu'] = u'User talk'
- self.namespaces[3]['id'] = u'Pembicaraan Pengguna'
- self.namespaces[3]['jv'] = u'Dhiskusi Panganggo'
- self.namespaces[3]['lb'] = u'Benotzer Diskussioun'
- self.namespaces[3]['lv'] = u'Lietotāja diskusija'
- self.namespaces[3]['mg'] = u'Discussion Utilisateur'
- self.namespaces[3]['mk'] = u'Разговор со корисник'
- self.namespaces[3]['pl'] = u'Dyskusja użytkownika'
- self.namespaces[3]['th'] = u'คุยกับผู้ใช้'
- self.namespaces[3]['zh-hk'] = u'用戶討論'
- self.namespaces[3]['zh-tw'] = u'用戶討論'
+ self.namespaces[3]['ast'] = u'Usuariu discusión'
+ self.namespaces[3]['bs'] = u'Razgovor sa korisnikom'
+ self.namespaces[3]['da'] = u'Brugerdiskussion'
+ self.namespaces[3]['hu'] = u'User talk'
+ self.namespaces[3]['id'] = u'Pembicaraan Pengguna'
+ self.namespaces[3]['jv'] = u'Dhiskusi Panganggo'
+ self.namespaces[3]['lb'] = u'Benotzer Diskussioun'
+ self.namespaces[3]['lv'] = u'Lietotāja diskusija'
+ self.namespaces[3]['mg'] = u'Discussion Utilisateur'
+ self.namespaces[3]['mk'] = u'Разговор со корисник'
+ self.namespaces[3]['pl'] = u'Dyskusja użytkownika'
+ self.namespaces[3]['th'] = u'คุยกับผู้ใช้'
+ self.namespaces[3]['zh-hk'] = u'用戶討論'
+ self.namespaces[3]['zh-tw'] = u'用戶討論'
- self.namespaces[4]['ar'] = u'بيضيپيديا'
- self.namespaces[4]['ast'] = u'Nunyepedia'
- self.namespaces[4]['bg'] = u'Oxypedia'
- self.namespaces[4]['bn'] = u'Uncyclopedia'
- self.namespaces[4]['bs'] = u'Neciklopedija'
- self.namespaces[4]['ca'] = u'Valenciclopèdia'
- self.namespaces[4]['common'] = u'UnCommons'
- self.namespaces[4]['cs'] = u'Necyklopedie'
- self.namespaces[4]['cy'] = u'Celwyddoniadur'
- self.namespaces[4]['da'] = u'Spademanns Leksikon'
- self.namespaces[4]['de'] = u'Uncyclopedia'
- self.namespaces[4]['el'] = u'Φρικηπαίδεια'
- self.namespaces[4]['en'] = u'Uncyclopedia'
- self.namespaces[4]['eo'] = u'Neciklopedio'
- self.namespaces[4]['es'] = u'Inciclopedia'
- self.namespaces[4]['et'] = u'Ebatsüklopeedia'
- self.namespaces[4]['fa'] = u'Uncyclopedia'
- self.namespaces[4]['fi'] = u'Hikipedia'
- self.namespaces[4]['fr'] = u'Désencyclopédie'
- self.namespaces[4]['got'] = u'Unsaiklopedia'
- self.namespaces[4]['he'] = u'איןציקלופדיה'
- self.namespaces[4]['hr'] = u'Neciklopedija'
- self.namespaces[4]['hu'] = u'Unciklopédia'
- self.namespaces[4]['id'] = u'Tolololpedia'
- self.namespaces[4]['info'] = u'Uncyclopaedia'
- self.namespaces[4]['it'] = u'Nonciclopedia'
- self.namespaces[4]['ja'] = u'Uncyclopedia'
- self.namespaces[4]['jv'] = u'Ndhablek'
- self.namespaces[4]['ko'] = u'백괴사전'
- self.namespaces[4]['la'] = u'Uncapaedia'
- self.namespaces[4]['lb'] = u'Kengencyclopedia'
- self.namespaces[4]['lt'] = u'Juokopediją'
- self.namespaces[4]['lv'] = u'Neciklopēdija'
- self.namespaces[4]['meta'] = u'UnMeta'
- self.namespaces[4]['mg'] = u'Hatsiklopedia'
- self.namespaces[4]['mk'] = u'Нециклопедий'
- self.namespaces[4]['nl'] = u'Oncyclopedie'
- self.namespaces[4]['nn'] = u'Ikkepedia'
- self.namespaces[4]['no'] = u'Ikkepedia'
- self.namespaces[4]['pl'] = u'Nonsensopedia'
- self.namespaces[4]['pt'] = u'Desciclopédia'
- self.namespaces[4]['ro'] = u'Unciclopedie'
- self.namespaces[4]['ru'] = u'Абсурдопедия'
- self.namespaces[4]['sk'] = u'Necyklopédia'
- self.namespaces[4]['sl'] = u'Butalopedija'
- self.namespaces[4]['sr'] = u'Нециклопедија'
- self.namespaces[4]['su'] = u'Goblogpedia Wiki'
- self.namespaces[4]['sv'] = u'Psyklopedin'
- self.namespaces[4]['th'] = u'ไร้สาระนุกรม'
- self.namespaces[4]['tr'] = u'Yansiklopedi'
- self.namespaces[4]['uk'] = u'Інциклопедія'
- self.namespaces[4]['yi'] = u'קיינציקלאָפעדיע'
- self.namespaces[4]['zh'] = u'伪基百科'
- self.namespaces[4]['zh-hk'] = u'偽基百科'
- self.namespaces[4]['zh-tw'] = u'偽基百科'
+ self.namespaces[4]['ar'] = u'بيضيپيديا'
+ self.namespaces[4]['ast'] = u'Nunyepedia'
+ self.namespaces[4]['bg'] = u'Oxypedia'
+ self.namespaces[4]['bn'] = u'Uncyclopedia'
+ self.namespaces[4]['bs'] = u'Neciklopedija'
+ self.namespaces[4]['ca'] = u'Valenciclopèdia'
+ self.namespaces[4]['common'] = u'UnCommons'
+ self.namespaces[4]['cs'] = u'Necyklopedie'
+ self.namespaces[4]['cy'] = u'Celwyddoniadur'
+ self.namespaces[4]['da'] = u'Spademanns Leksikon'
+ self.namespaces[4]['de'] = u'Uncyclopedia'
+ self.namespaces[4]['el'] = u'Φρικηπαίδεια'
+ self.namespaces[4]['en'] = u'Uncyclopedia'
+ self.namespaces[4]['eo'] = u'Neciklopedio'
+ self.namespaces[4]['es'] = u'Inciclopedia'
+ self.namespaces[4]['et'] = u'Ebatsüklopeedia'
+ self.namespaces[4]['fa'] = u'Uncyclopedia'
+ self.namespaces[4]['fi'] = u'Hikipedia'
+ self.namespaces[4]['fr'] = u'Désencyclopédie'
+ self.namespaces[4]['got'] = u'Unsaiklopedia'
+ self.namespaces[4]['he'] = u'איןציקלופדיה'
+ self.namespaces[4]['hr'] = u'Neciklopedija'
+ self.namespaces[4]['hu'] = u'Unciklopédia'
+ self.namespaces[4]['id'] = u'Tolololpedia'
+ self.namespaces[4]['info'] = u'Uncyclopaedia'
+ self.namespaces[4]['it'] = u'Nonciclopedia'
+ self.namespaces[4]['ja'] = u'Uncyclopedia'
+ self.namespaces[4]['jv'] = u'Ndhablek'
+ self.namespaces[4]['ko'] = u'백괴사전'
+ self.namespaces[4]['la'] = u'Uncapaedia'
+ self.namespaces[4]['lb'] = u'Kengencyclopedia'
+ self.namespaces[4]['lt'] = u'Juokopediją'
+ self.namespaces[4]['lv'] = u'Neciklopēdija'
+ self.namespaces[4]['meta'] = u'UnMeta'
+ self.namespaces[4]['mg'] = u'Hatsiklopedia'
+ self.namespaces[4]['mk'] = u'Нециклопедий'
+ self.namespaces[4]['nl'] = u'Oncyclopedie'
+ self.namespaces[4]['nn'] = u'Ikkepedia'
+ self.namespaces[4]['no'] = u'Ikkepedia'
+ self.namespaces[4]['pl'] = u'Nonsensopedia'
+ self.namespaces[4]['pt'] = u'Desciclopédia'
+ self.namespaces[4]['ro'] = u'Unciclopedie'
+ self.namespaces[4]['ru'] = u'Абсурдопедия'
+ self.namespaces[4]['sk'] = u'Necyklopédia'
+ self.namespaces[4]['sl'] = u'Butalopedija'
+ self.namespaces[4]['sr'] = u'Нециклопедија'
+ self.namespaces[4]['su'] = u'Goblogpedia Wiki'
+ self.namespaces[4]['sv'] = u'Psyklopedin'
+ self.namespaces[4]['th'] = u'ไร้สาระนุกรม'
+ self.namespaces[4]['tr'] = u'Yansiklopedi'
+ self.namespaces[4]['uk'] = u'Інциклопедія'
+ self.namespaces[4]['yi'] = u'קיינציקלאָפעדיע'
+ self.namespaces[4]['zh'] = u'伪基百科'
+ self.namespaces[4]['zh-hk'] = u'偽基百科'
+ self.namespaces[4]['zh-tw'] = u'偽基百科'
- self.namespaces[5]['ar'] = u'نقاش بيضيپيديا'
- self.namespaces[5]['ast'] = u'Nunyepedia discusión'
- self.namespaces[5]['bg'] = u'Oxypedia беседа'
- self.namespaces[5]['bn'] = u'Uncyclopedia আলাপ'
- self.namespaces[5]['bs'] = u'Razgovor s Neciklopedija'
- self.namespaces[5]['ca'] = u'Valenciclopèdia Discussió'
- self.namespaces[5]['common'] = u'UnCommon talk'
- self.namespaces[5]['cs'] = u'Necyklopedie diskuse'
- self.namespaces[5]['cy'] = u'Sgwrs Celwyddoniadur'
- self.namespaces[5]['da'] = u'Spademanns Leksikon-diskussion'
- self.namespaces[5]['de'] = u'Uncyclopedia Diskussion'
- self.namespaces[5]['el'] = u'Φρικηπαίδεια συζήτηση'
- self.namespaces[5]['en'] = u'Uncyclopedia talk'
- self.namespaces[5]['eo'] = u'Neciklopedio diskuto'
- self.namespaces[5]['es'] = u'Inciclopedia Discusión'
- self.namespaces[5]['et'] = u'Ebatsüklopeedia arutelu'
- self.namespaces[5]['fa'] = u'بحث Uncyclopedia'
- self.namespaces[5]['fi'] = u'Keskustelu Hikipediasta'
- self.namespaces[5]['fr'] = u'Discussion Désencyclopédie'
- self.namespaces[5]['got'] = u'Unsaiklopedia talk'
- self.namespaces[5]['he'] = u'שיחת איןציקלופדיה'
- self.namespaces[5]['hr'] = u'Razgovor Neciklopedija'
- self.namespaces[5]['hu'] = u'Unciklopédia vita'
- self.namespaces[5]['id'] = u'Pembicaraan Tolololpedia'
- self.namespaces[5]['info'] = u'Uncyclopædia talk'
- self.namespaces[5]['it'] = u'Discussioni Nonciclopedia'
- self.namespaces[5]['ja'] = u'Uncyclopedia talk'
- self.namespaces[5]['jv'] = u'Dhiskusi Ndhablek'
- self.namespaces[5]['ko'] = u'백괴사전토론'
- self.namespaces[5]['la'] = u'Disputatio Uncapaediae'
- self.namespaces[5]['lb'] = u'Kengencyclopedia Diskussioun'
- self.namespaces[5]['lt'] = u'Juokopediją aptarimas'
- self.namespaces[5]['lv'] = u'Neciklopēdija diskusija'
- self.namespaces[5]['meta'] = u'UnMeta talk'
- self.namespaces[5]['mg'] = u'Discussion Hatsiklopedia'
- self.namespaces[5]['mk'] = u'Разговор за Нециклопедий'
- self.namespaces[5]['nl'] = u'Overleg Oncyclopedie'
- self.namespaces[5]['nn'] = u'Ikkepedia-diskusjon'
- self.namespaces[5]['no'] = u'Ikkepedia-diskusjon'
- self.namespaces[5]['pl'] = u'Dyskusja Nonsensopedia'
- self.namespaces[5]['pt'] = u'Desciclopédia Discussão'
- self.namespaces[5]['ro'] = u'Discuţie Unciclopedie'
- self.namespaces[5]['ru'] = u'Обсуждение Абсурдопедии'
- self.namespaces[5]['sk'] = u'Diskusia k Necyklopédia'
- self.namespaces[5]['sl'] = u'Pogovor o Butalopedija'
- self.namespaces[5]['sr'] = u'Разговор о Нециклопедија'
- self.namespaces[5]['su'] = u'Obrolan Goblogpedia Wiki'
- self.namespaces[5]['sv'] = u'Psyklopedindiskussion'
- self.namespaces[5]['th'] = u'คุยเรื่องไร้สาระนุกรม'
- self.namespaces[5]['tr'] = u'Yansiklopedi tartışma'
- self.namespaces[5]['uk'] = u'Обговорення Інциклопедії'
- self.namespaces[5]['yi'] = u'קיינציקלאָפעדיע רעדן'
- self.namespaces[5]['zh'] = u'伪基百科 talk'
- self.namespaces[5]['zh-hk'] = u'偽基百科討論'
- self.namespaces[5]['zh-tw'] = u'偽基百科討論'
+ self.namespaces[5]['ar'] = u'نقاش بيضيپيديا'
+ self.namespaces[5]['ast'] = u'Nunyepedia discusión'
+ self.namespaces[5]['bg'] = u'Oxypedia беседа'
+ self.namespaces[5]['bn'] = u'Uncyclopedia আলাপ'
+ self.namespaces[5]['bs'] = u'Razgovor s Neciklopedija'
+ self.namespaces[5]['ca'] = u'Valenciclopèdia Discussió'
+ self.namespaces[5]['common'] = u'UnCommon talk'
+ self.namespaces[5]['cs'] = u'Necyklopedie diskuse'
+ self.namespaces[5]['cy'] = u'Sgwrs Celwyddoniadur'
+ self.namespaces[5]['da'] = u'Spademanns Leksikon-diskussion'
+ self.namespaces[5]['de'] = u'Uncyclopedia Diskussion'
+ self.namespaces[5]['el'] = u'Φρικηπαίδεια συζήτηση'
+ self.namespaces[5]['en'] = u'Uncyclopedia talk'
+ self.namespaces[5]['eo'] = u'Neciklopedio diskuto'
+ self.namespaces[5]['es'] = u'Inciclopedia Discusión'
+ self.namespaces[5]['et'] = u'Ebatsüklopeedia arutelu'
+ self.namespaces[5]['fa'] = u'بحث Uncyclopedia'
+ self.namespaces[5]['fi'] = u'Keskustelu Hikipediasta'
+ self.namespaces[5]['fr'] = u'Discussion Désencyclopédie'
+ self.namespaces[5]['got'] = u'Unsaiklopedia talk'
+ self.namespaces[5]['he'] = u'שיחת איןציקלופדיה'
+ self.namespaces[5]['hr'] = u'Razgovor Neciklopedija'
+ self.namespaces[5]['hu'] = u'Unciklopédia vita'
+ self.namespaces[5]['id'] = u'Pembicaraan Tolololpedia'
+ self.namespaces[5]['info'] = u'Uncyclopædia talk'
+ self.namespaces[5]['it'] = u'Discussioni Nonciclopedia'
+ self.namespaces[5]['ja'] = u'Uncyclopedia talk'
+ self.namespaces[5]['jv'] = u'Dhiskusi Ndhablek'
+ self.namespaces[5]['ko'] = u'백괴사전토론'
+ self.namespaces[5]['la'] = u'Disputatio Uncapaediae'
+ self.namespaces[5]['lb'] = u'Kengencyclopedia Diskussioun'
+ self.namespaces[5]['lt'] = u'Juokopediją aptarimas'
+ self.namespaces[5]['lv'] = u'Neciklopēdija diskusija'
+ self.namespaces[5]['meta'] = u'UnMeta talk'
+ self.namespaces[5]['mg'] = u'Discussion Hatsiklopedia'
+ self.namespaces[5]['mk'] = u'Разговор за Нециклопедий'
+ self.namespaces[5]['nl'] = u'Overleg Oncyclopedie'
+ self.namespaces[5]['nn'] = u'Ikkepedia-diskusjon'
+ self.namespaces[5]['no'] = u'Ikkepedia-diskusjon'
+ self.namespaces[5]['pl'] = u'Dyskusja Nonsensopedia'
+ self.namespaces[5]['pt'] = u'Desciclopédia Discussão'
+ self.namespaces[5]['ro'] = u'Discuţie Unciclopedie'
+ self.namespaces[5]['ru'] = u'Обсуждение Абсурдопедии'
+ self.namespaces[5]['sk'] = u'Diskusia k Necyklopédia'
+ self.namespaces[5]['sl'] = u'Pogovor o Butalopedija'
+ self.namespaces[5]['sr'] = u'Разговор о Нециклопедија'
+ self.namespaces[5]['su'] = u'Obrolan Goblogpedia Wiki'
+ self.namespaces[5]['sv'] = u'Psyklopedindiskussion'
+ self.namespaces[5]['th'] = u'คุยเรื่องไร้สาระนุกรม'
+ self.namespaces[5]['tr'] = u'Yansiklopedi tartışma'
+ self.namespaces[5]['uk'] = u'Обговорення Інциклопедії'
+ self.namespaces[5]['yi'] = u'קיינציקלאָפעדיע רעדן'
+ self.namespaces[5]['zh'] = u'伪基百科 talk'
+ self.namespaces[5]['zh-hk'] = u'偽基百科討論'
+ self.namespaces[5]['zh-tw'] = u'偽基百科討論'
- self.namespaces[6]['ast'] = u'Imaxen'
- self.namespaces[6]['bs'] = u'Slika'
- self.namespaces[6]['id'] = u'Berkas'
- self.namespaces[6]['info'] = u'File'
- self.namespaces[6]['ja'] = u'Image'
- self.namespaces[6]['jv'] = u'Gambar'
- self.namespaces[6]['lb'] = u'Bild'
- self.namespaces[6]['lv'] = u'Attēls'
- self.namespaces[6]['zh-hk'] = u'圖像'
- self.namespaces[6]['zh-tw'] = u'圖像'
+ self.namespaces[6]['ast'] = u'Imaxen'
+ self.namespaces[6]['bs'] = u'Slika'
+ self.namespaces[6]['id'] = u'Berkas'
+ self.namespaces[6]['info'] = u'File'
+ self.namespaces[6]['ja'] = u'Image'
+ self.namespaces[6]['jv'] = u'Gambar'
+ self.namespaces[6]['lb'] = u'Bild'
+ self.namespaces[6]['lv'] = u'Attēls'
+ self.namespaces[6]['zh-hk'] = u'圖像'
+ self.namespaces[6]['zh-tw'] = u'圖像'
- self.namespaces[7]['ast'] = u'Imaxen discusión'
- self.namespaces[7]['bs'] = u'Razgovor o slici'
- self.namespaces[7]['da'] = u'Billeddiskussion'
- self.namespaces[7]['hu'] = u'Kep vita'
- self.namespaces[7]['id'] = u'Pembicaraan Berkas'
- self.namespaces[7]['info'] = u'File talk'
- self.namespaces[7]['jv'] = u'Dhiskusi Gambar'
- self.namespaces[7]['lb'] = u'Bild Diskussioun'
- self.namespaces[7]['lv'] = u'Attēla diskusija'
- self.namespaces[7]['mg'] = u'Discussion Image'
- self.namespaces[7]['mk'] = u'Разговор за слика'
- self.namespaces[7]['th'] = u'คุยเรื่องภาพ'
- self.namespaces[7]['zh-hk'] = u'圖像討論'
- self.namespaces[7]['zh-tw'] = u'圖像討論'
+ self.namespaces[7]['ast'] = u'Imaxen discusión'
+ self.namespaces[7]['bs'] = u'Razgovor o slici'
+ self.namespaces[7]['da'] = u'Billeddiskussion'
+ self.namespaces[7]['hu'] = u'Kep vita'
+ self.namespaces[7]['id'] = u'Pembicaraan Berkas'
+ self.namespaces[7]['info'] = u'File talk'
+ self.namespaces[7]['jv'] = u'Dhiskusi Gambar'
+ self.namespaces[7]['lb'] = u'Bild Diskussioun'
+ self.namespaces[7]['lv'] = u'Attēla diskusija'
+ self.namespaces[7]['mg'] = u'Discussion Image'
+ self.namespaces[7]['mk'] = u'Разговор за слика'
+ self.namespaces[7]['th'] = u'คุยเรื่องภาพ'
+ self.namespaces[7]['zh-hk'] = u'圖像討論'
+ self.namespaces[7]['zh-tw'] = u'圖像討論'
- self.namespaces[8]['bs'] = u'MedijaViki'
- self.namespaces[8]['fi'] = u'MediaWiki'
- self.namespaces[8]['cy'] = u'MediaWici'
- self.namespaces[8]['he'] = u'מדיה ויקי'
- self.namespaces[8]['lb'] = u'MediaWiki'
- self.namespaces[8]['th'] = u'มีเดียวิกิ'
- self.namespaces[8]['zh-hk'] = u'媒體偽基'
- self.namespaces[8]['zh-tw'] = u'媒體偽基'
+ self.namespaces[8]['bs'] = u'MedijaViki'
+ self.namespaces[8]['fi'] = u'MediaWiki'
+ self.namespaces[8]['cy'] = u'MediaWici'
+ self.namespaces[8]['he'] = u'מדיה ויקי'
+ self.namespaces[8]['lb'] = u'MediaWiki'
+ self.namespaces[8]['th'] = u'มีเดียวิกิ'
+ self.namespaces[8]['zh-hk'] = u'媒體偽基'
+ self.namespaces[8]['zh-tw'] = u'媒體偽基'
- self.namespaces[9]['ast'] = u'MediaWiki discusión'
- self.namespaces[9]['bn'] = u'MediaWiki আলাপ'
- self.namespaces[9]['bs'] = u'Razgovor o MedijaVikiju'
- self.namespaces[9]['cy'] = u'Sgwrs MediaWici'
- self.namespaces[9]['da'] = u'MediaWiki-diskussion'
- self.namespaces[9]['fi'] = u'Keskustelu MediaWiki'
- self.namespaces[9]['he'] = u'שיחת מדיה ויקי'
- self.namespaces[9]['hu'] = u'MediaWiki talk'
- self.namespaces[9]['jv'] = u'Dhiskusi MediaWiki'
- self.namespaces[9]['ko'] = u'MediaWiki토론'
- self.namespaces[9]['lb'] = u'MediaWiki Diskussioun'
- self.namespaces[9]['lv'] = u'MediaWiki diskusija'
- self.namespaces[9]['mg'] = u'Discussion MediaWiki'
- self.namespaces[9]['mk'] = u'Разговор за МедијаВики'
- self.namespaces[9]['sv'] = u'MediaWiki diskussion'
- self.namespaces[9]['th'] = u'คุยเรื่องมีเดียวิกิ'
- self.namespaces[9]['zh-hk'] = u'媒體偽基討論'
- self.namespaces[9]['zh-tw'] = u'媒體偽基討論'
+ self.namespaces[9]['ast'] = u'MediaWiki discusión'
+ self.namespaces[9]['bn'] = u'MediaWiki আলাপ'
+ self.namespaces[9]['bs'] = u'Razgovor o MedijaVikiju'
+ self.namespaces[9]['cy'] = u'Sgwrs MediaWici'
+ self.namespaces[9]['da'] = u'MediaWiki-diskussion'
+ self.namespaces[9]['fi'] = u'Keskustelu MediaWiki'
+ self.namespaces[9]['he'] = u'שיחת מדיה ויקי'
+ self.namespaces[9]['hu'] = u'MediaWiki talk'
+ self.namespaces[9]['jv'] = u'Dhiskusi MediaWiki'
+ self.namespaces[9]['ko'] = u'MediaWiki토론'
+ self.namespaces[9]['lb'] = u'MediaWiki Diskussioun'
+ self.namespaces[9]['lv'] = u'MediaWiki diskusija'
+ self.namespaces[9]['mg'] = u'Discussion MediaWiki'
+ self.namespaces[9]['mk'] = u'Разговор за МедијаВики'
+ self.namespaces[9]['sv'] = u'MediaWiki diskussion'
+ self.namespaces[9]['th'] = u'คุยเรื่องมีเดียวิกิ'
+ self.namespaces[9]['zh-hk'] = u'媒體偽基討論'
+ self.namespaces[9]['zh-tw'] = u'媒體偽基討論'
- self.namespaces[10]['ast'] = u'Plantilla'
- self.namespaces[10]['bs'] = u'Šablon'
- self.namespaces[10]['ca'] = u'Plantilla'
- self.namespaces[10]['jv'] = u'Cithakan'
- self.namespaces[10]['ko'] = u'틀'
- self.namespaces[10]['lb'] = u'Schabloun'
- self.namespaces[10]['lv'] = u'Veidne'
- self.namespaces[10]['mg'] = u'Modèle'
- self.namespaces[10]['mk'] = u'Шаблон'
- self.namespaces[10]['th'] = u'แม่แบบ'
- self.namespaces[10]['zh-hk'] = u'範本'
- self.namespaces[10]['zh-tw'] = u'範本'
+ self.namespaces[10]['ast'] = u'Plantilla'
+ self.namespaces[10]['bs'] = u'Šablon'
+ self.namespaces[10]['ca'] = u'Plantilla'
+ self.namespaces[10]['jv'] = u'Cithakan'
+ self.namespaces[10]['ko'] = u'틀'
+ self.namespaces[10]['lb'] = u'Schabloun'
+ self.namespaces[10]['lv'] = u'Veidne'
+ self.namespaces[10]['mg'] = u'Modèle'
+ self.namespaces[10]['mk'] = u'Шаблон'
+ self.namespaces[10]['th'] = u'แม่แบบ'
+ self.namespaces[10]['zh-hk'] = u'範本'
+ self.namespaces[10]['zh-tw'] = u'範本'
- self.namespaces[11]['ar'] = u'نقاش قالب'
- self.namespaces[11]['ast'] = u'Plantilla discusión'
- self.namespaces[11]['bs'] = u'Razgovor o šablonu'
- self.namespaces[11]['ca'] = u'Plantilla Discussió'
- self.namespaces[11]['da'] = u'Skabelondiskussion'
- self.namespaces[11]['jv'] = u'Dhiskusi Cithakan'
- self.namespaces[11]['ko'] = u'틀토론'
- self.namespaces[11]['lb'] = u'Schabloun Diskussioun'
- self.namespaces[11]['lv'] = u'Veidnes diskusija'
- self.namespaces[11]['mg'] = u'Discussion Modèle'
- self.namespaces[11]['mk'] = u'Разговор за шаблон'
- self.namespaces[11]['th'] = u'คุยเรื่องแม่แบบ'
- self.namespaces[11]['zh-hk'] = u'範本討論'
- self.namespaces[11]['zh-tw'] = u'範本討論'
+ self.namespaces[11]['ar'] = u'نقاش قالب'
+ self.namespaces[11]['ast'] = u'Plantilla discusión'
+ self.namespaces[11]['bs'] = u'Razgovor o šablonu'
+ self.namespaces[11]['ca'] = u'Plantilla Discussió'
+ self.namespaces[11]['da'] = u'Skabelondiskussion'
+ self.namespaces[11]['jv'] = u'Dhiskusi Cithakan'
+ self.namespaces[11]['ko'] = u'틀토론'
+ self.namespaces[11]['lb'] = u'Schabloun Diskussioun'
+ self.namespaces[11]['lv'] = u'Veidnes diskusija'
+ self.namespaces[11]['mg'] = u'Discussion Modèle'
+ self.namespaces[11]['mk'] = u'Разговор за шаблон'
+ self.namespaces[11]['th'] = u'คุยเรื่องแม่แบบ'
+ self.namespaces[11]['zh-hk'] = u'範本討論'
+ self.namespaces[11]['zh-tw'] = u'範本討論'
- self.namespaces[12]['ast'] = u'Ayuda'
- self.namespaces[12]['bs'] = u'Pomoć'
- self.namespaces[12]['cy'] = u'Cymorth'
- self.namespaces[12]['jv'] = u'Pitulung'
- self.namespaces[12]['lb'] = u'Hëllef'
- self.namespaces[12]['lv'] = u'Palīdzība'
- self.namespaces[12]['mg'] = u'Aide'
- self.namespaces[12]['th'] = u'วิธีใช้'
- self.namespaces[12]['zh-hk'] = u'協助'
- self.namespaces[12]['zh-tw'] = u'協助'
+ self.namespaces[12]['ast'] = u'Ayuda'
+ self.namespaces[12]['bs'] = u'Pomoć'
+ self.namespaces[12]['cy'] = u'Cymorth'
+ self.namespaces[12]['jv'] = u'Pitulung'
+ self.namespaces[12]['lb'] = u'Hëllef'
+ self.namespaces[12]['lv'] = u'Palīdzība'
+ self.namespaces[12]['mg'] = u'Aide'
+ self.namespaces[12]['th'] = u'วิธีใช้'
+ self.namespaces[12]['zh-hk'] = u'協助'
+ self.namespaces[12]['zh-tw'] = u'協助'
- self.namespaces[13]['ast'] = u'Ayuda discusión'
- self.namespaces[13]['bs'] = u'Razgovor o pomoći'
- self.namespaces[13]['cy'] = u'Sgwrs Cymorth'
- self.namespaces[13]['da'] = u'Hjælp-diskussion'
- self.namespaces[13]['jv'] = u'Dhiskusi Pitulung'
- self.namespaces[13]['lb'] = u'Hëllef Diskussioun'
- self.namespaces[13]['lv'] = u'Palīdzības diskusija'
- self.namespaces[13]['mg'] = u'Discussion Aide'
- self.namespaces[13]['mk'] = u'Разговор за помош'
- self.namespaces[13]['sv'] = u'Hjälpdiskussion'
- self.namespaces[13]['th'] = u'คุยเรื่องวิธีใช้'
- self.namespaces[13]['zh-hk'] = u'協助討論'
- self.namespaces[13]['zh-tw'] = u'協助討論'
+ self.namespaces[13]['ast'] = u'Ayuda discusión'
+ self.namespaces[13]['bs'] = u'Razgovor o pomoći'
+ self.namespaces[13]['cy'] = u'Sgwrs Cymorth'
+ self.namespaces[13]['da'] = u'Hjælp-diskussion'
+ self.namespaces[13]['jv'] = u'Dhiskusi Pitulung'
+ self.namespaces[13]['lb'] = u'Hëllef Diskussioun'
+ self.namespaces[13]['lv'] = u'Palīdzības diskusija'
+ self.namespaces[13]['mg'] = u'Discussion Aide'
+ self.namespaces[13]['mk'] = u'Разговор за помош'
+ self.namespaces[13]['sv'] = u'Hjälpdiskussion'
+ self.namespaces[13]['th'] = u'คุยเรื่องวิธีใช้'
+ self.namespaces[13]['zh-hk'] = u'協助討論'
+ self.namespaces[13]['zh-tw'] = u'協助討論'
- self.namespaces[14]['bs'] = u'Kategorija'
- self.namespaces[14]['cy'] = u'Categori'
- self.namespaces[14]['jv'] = u'Kategori'
- self.namespaces[14]['lb'] = u'Kategorie'
- self.namespaces[14]['lv'] = u'Kategorija'
- self.namespaces[14]['mg'] = u'Catégorie'
- self.namespaces[14]['th'] = u'หมวดหมู่'
- self.namespaces[14]['zh-hk'] = u'分類'
- self.namespaces[14]['zh-tw'] = u'分類'
+ self.namespaces[14]['bs'] = u'Kategorija'
+ self.namespaces[14]['cy'] = u'Categori'
+ self.namespaces[14]['jv'] = u'Kategori'
+ self.namespaces[14]['lb'] = u'Kategorie'
+ self.namespaces[14]['lv'] = u'Kategorija'
+ self.namespaces[14]['mg'] = u'Catégorie'
+ self.namespaces[14]['th'] = u'หมวดหมู่'
+ self.namespaces[14]['zh-hk'] = u'分類'
+ self.namespaces[14]['zh-tw'] = u'分類'
- self.namespaces[15]['ast'] = u'Categoría discusión'
- self.namespaces[15]['bg'] = u'Категория беседа'
- self.namespaces[15]['bs'] = u'Razgovor o kategoriji'
- self.namespaces[15]['cy'] = u'Sgwrs Categori'
- self.namespaces[15]['da'] = u'Kategoridiskussion'
- self.namespaces[15]['jv'] = u'Dhiskusi Kategori'
- self.namespaces[15]['lb'] = u'Kategorie Diskussioun'
- self.namespaces[15]['lv'] = u'Kategorijas diskusija'
- self.namespaces[15]['mg'] = u'Discussion Catégorie'
- self.namespaces[15]['mk'] = u'Разговор за категорија'
- self.namespaces[15]['th'] = u'คุยเรื่องหมวดหมู่'
- self.namespaces[15]['zh-hk'] = u'分類討論'
- self.namespaces[15]['zh-tw'] = u'分類討論'
+ self.namespaces[15]['ast'] = u'Categoría discusión'
+ self.namespaces[15]['bg'] = u'Категория беседа'
+ self.namespaces[15]['bs'] = u'Razgovor o kategoriji'
+ self.namespaces[15]['cy'] = u'Sgwrs Categori'
+ self.namespaces[15]['da'] = u'Kategoridiskussion'
+ self.namespaces[15]['jv'] = u'Dhiskusi Kategori'
+ self.namespaces[15]['lb'] = u'Kategorie Diskussioun'
+ self.namespaces[15]['lv'] = u'Kategorijas diskusija'
+ self.namespaces[15]['mg'] = u'Discussion Catégorie'
+ self.namespaces[15]['mk'] = u'Разговор за категорија'
+ self.namespaces[15]['th'] = u'คุยเรื่องหมวดหมู่'
+ self.namespaces[15]['zh-hk'] = u'分類討論'
+ self.namespaces[15]['zh-tw'] = u'分類討論'
- self.namespaces[16] = {
- 'fi': u'Foorumi',
- 'got': u'Forum',
- 'info': u'Game',
-# 'ko': u'漢字',
- 'meta': u'UnSource',
- 'nl': u'Portaal',
- 'pt': u'Esplanada',
- 'th': u'อันไซโคลพีเดีย',
- 'zh-hk': u'偽基新聞',
- 'zh-tw': u'偽基新聞'
- }
+ self.namespaces[16] = {
+ 'fi': u'Foorumi',
+ 'got': u'Forum',
+ 'info': u'Game',
+# 'ko': u'漢字',
+ 'meta': u'UnSource',
+ 'nl': u'Portaal',
+ 'pt': u'Esplanada',
+ 'th': u'อันไซโคลพีเดีย',
+ 'zh-hk': u'偽基新聞',
+ 'zh-tw': u'偽基新聞'
+ }
- self.namespaces[17] = {
- 'fi': u'Keskustelu foorumista',
- 'got': u'Forum gawaurdja',
- 'info': u'Game talk',
-# 'ko': u'討論',
- 'meta': u'UnSource talk',
- 'nl': u'Overleg portaal',
- 'pt': u'Esplanada Discussão',
- 'th': u'คุยเรื่องอันไซโคลพีเดีย',
- 'zh-hk': u'偽基新聞討論',
- 'zh-tw': u'偽基新聞討論'
- }
+ self.namespaces[17] = {
+ 'fi': u'Keskustelu foorumista',
+ 'got': u'Forum gawaurdja',
+ 'info': u'Game talk',
+# 'ko': u'討論',
+ 'meta': u'UnSource talk',
+ 'nl': u'Overleg portaal',
+ 'pt': u'Esplanada Discussão',
+ 'th': u'คุยเรื่องอันไซโคลพีเดีย',
+ 'zh-hk': u'偽基新聞討論',
+ 'zh-tw': u'偽基新聞討論'
+ }
- self.namespaces[18] = {
- '_default': '',
- 'fi': u'Hikinews',
- 'got': u'𐌰𐍂𐌼𐌰𐌹𐍉',
-# 'ko': u'백괴나라',
- 'meta': u'UnSpecies',
- 'nl': u'OnNieuws',
- 'pt': u'Fatos',
- 'th': u'ไร้ข่าว',
- 'zh-hk': u'偽基辭典',
- 'zh-tw': u'偽基辭典'
- }
+ self.namespaces[18] = {
+ '_default': '',
+ 'fi': u'Hikinews',
+ 'got': u'𐌰𐍂𐌼𐌰𐌹𐍉',
+# 'ko': u'백괴나라',
+ 'meta': u'UnSpecies',
+ 'nl': u'OnNieuws',
+ 'pt': u'Fatos',
+ 'th': u'ไร้ข่าว',
+ 'zh-hk': u'偽基辭典',
+ 'zh-tw': u'偽基辭典'
+ }
- self.namespaces[19] = {
- '_default': '',
- 'fi': u'Keskustelu Hikinewseistä',
- 'got': u'𐌰𐍂𐌼𐌰𐌹𐍉 𐌲𐌰𐍅𐌰𐌿𐍂𐌳𐌾𐌰',
-# 'ko': u'백괴나라토론',
- 'meta': u'UnSpecies talk',
- 'nl': u'Overleg OnNieuws',
- 'pt': u'Fatos Discussão',
- 'th': u'คุยเรื่องไร้ข่าว',
- 'zh-hk': u'偽基辭典討論',
- 'zh-tw': u'偽基辭典討論'
- }
+ self.namespaces[19] = {
+ '_default': '',
+ 'fi': u'Keskustelu Hikinewseistä',
+ 'got': u'𐌰𐍂𐌼𐌰𐌹𐍉 𐌲𐌰𐍅𐌰𐌿𐍂𐌳𐌾𐌰',
+# 'ko': u'백괴나라토론',
+ 'meta': u'UnSpecies talk',
+ 'nl': u'Overleg OnNieuws',
+ 'pt': u'Fatos Discussão',
+ 'th': u'คุยเรื่องไร้ข่าว',
+ 'zh-hk': u'偽基辭典討論',
+ 'zh-tw': u'偽基辭典討論'
+ }
- self.namespaces[20] = {
- '_default': '',
- 'fi': u'Hiktionary',
- 'got': u'𐍆𐌰𐌹𐌰𐌽𐍅𐌰𐌿𐍂𐌳𐌰𐌱𐍉𐌺𐌰',
- 'meta': u'Namespace',
- 'nl': u'Onwoordenboek',
- 'pt': u'Forum',
- 'th': u'ไร้วิทยาลัย',
- 'zh-hk': u'動漫遊戲',
- 'zh-tw': u'動漫遊戲'
- }
+ self.namespaces[20] = {
+ '_default': '',
+ 'fi': u'Hiktionary',
+ 'got': u'𐍆𐌰𐌹𐌰𐌽𐍅𐌰𐌿𐍂𐌳𐌰𐌱𐍉𐌺𐌰',
+ 'meta': u'Namespace',
+ 'nl': u'Onwoordenboek',
+ 'pt': u'Forum',
+ 'th': u'ไร้วิทยาลัย',
+ 'zh-hk': u'動漫遊戲',
+ 'zh-tw': u'動漫遊戲'
+ }
- self.namespaces[21] = {
- '_default': '',
- 'fi': u'Keskustelu Hiktionarysta',
- 'got': u'𐍆𐌰𐌹𐌰𐌽𐍅𐌰𐌿𐍂𐌳𐌰𐌱𐍉𐌺𐌰 𐌲𐌰𐍅𐌰𐌿𐍂𐌳𐌾𐌰',
- 'meta': u'Namespace talk',
- 'nl': u'Overleg Onwoordenboek',
- 'pt': u'Forum Discussão',
- 'th': u'คุยเรื่องไร้วิทยาลัย',
- 'zh-hk': u'動漫遊戲討論',
- 'zh-tw': u'動漫遊戲討論'
- }
+ self.namespaces[21] = {
+ '_default': '',
+ 'fi': u'Keskustelu Hiktionarysta',
+ 'got': u'𐍆𐌰𐌹𐌰𐌽𐍅𐌰𐌿𐍂𐌳𐌰𐌱𐍉𐌺𐌰 𐌲𐌰𐍅𐌰𐌿𐍂𐌳𐌾𐌰',
+ 'meta': u'Namespace talk',
+ 'nl': u'Overleg Onwoordenboek',
+ 'pt': u'Forum Discussão',
+ 'th': u'คุยเรื่องไร้วิทยาลัย',
+ 'zh-hk': u'動漫遊戲討論',
+ 'zh-tw': u'動漫遊戲討論'
+ }
- self.namespaces[22] = {
- 'fi': u'Hikikirjasto',
- 'nl': u'OnBoeken',
- 'th': u'ไร้พจนานุกรม',
- 'zh-hk': u'春心蕩漾',
- 'zh-tw': u'春心蕩漾'
- }
+ self.namespaces[22] = {
+ 'fi': u'Hikikirjasto',
+ 'nl': u'OnBoeken',
+ 'th': u'ไร้พจนานุกรม',
+ 'zh-hk': u'春心蕩漾',
+ 'zh-tw': u'春心蕩漾'
+ }
- self.namespaces[23] = {
- 'fi': u'Keskustelu hikikirjasta',
- 'nl': u'Overleg OnBoeken',
- 'th': u'คุยเรื่องไร้พจนานุกรม',
- 'zh-hk': u'春心蕩漾討論',
- 'zh-tw': u'春心蕩漾討論'
- }
+ self.namespaces[23] = {
+ 'fi': u'Keskustelu hikikirjasta',
+ 'nl': u'Overleg OnBoeken',
+ 'th': u'คุยเรื่องไร้พจนานุกรม',
+ 'zh-hk': u'春心蕩漾討論',
+ 'zh-tw': u'春心蕩漾討論'
+ }
- self.namespaces[24] = {
- 'fi': u'Hikisitaatit',
- 'th': u'ไร้ชีวประวัติ',
- 'zh-hk': u'主題展館',
- 'zh-tw': u'主題展館'
- }
+ self.namespaces[24] = {
+ 'fi': u'Hikisitaatit',
+ 'th': u'ไร้ชีวประวัติ',
+ 'zh-hk': u'主題展館',
+ 'zh-tw': u'主題展館'
+ }
- self.namespaces[25] = {
- 'fi': u'Keskustelu hikisitaatista',
- 'th': u'คุยเรื่องไร้ชีวประวัติ',
- 'zh-hk': u'主題展館討論',
- 'zh-tw': u'主題展館討論'
- }
+ self.namespaces[25] = {
+ 'fi': u'Keskustelu hikisitaatista',
+ 'th': u'คุยเรื่องไร้ชีวประวัติ',
+ 'zh-hk': u'主題展館討論',
+ 'zh-tw': u'主題展館討論'
+ }
- self.namespaces[26] = {
- 'fi': u'Hömppäpedia',
- 'th': u'สภาน้ำชา',
- 'zh-hk': u'論壇',
- 'zh-tw': u'論壇'
- }
+ self.namespaces[26] = {
+ 'fi': u'Hömppäpedia',
+ 'th': u'สภาน้ำชา',
+ 'zh-hk': u'論壇',
+ 'zh-tw': u'論壇'
+ }
- self.namespaces[27] = {
- 'fi': u'Höpinä hömpästä',
- 'th': u'คุยเรื่องสภาน้ำชา',
- 'zh-hk': u'論壇討論',
- 'zh-tw': u'論壇討論'
- }
+ self.namespaces[27] = {
+ 'fi': u'Höpinä hömpästä',
+ 'th': u'คุยเรื่องสภาน้ำชา',
+ 'zh-hk': u'論壇討論',
+ 'zh-tw': u'論壇討論'
+ }
- self.namespaces[28] = {
- 'fi': u'Hikipeli',
- 'nl': u'Ongerijmd',
- 'th': u'บอร์ด',
- 'zh-hk': u'詞意分道',
- 'zh-tw': u'詞意分道'
- }
+ self.namespaces[28] = {
+ 'fi': u'Hikipeli',
+ 'nl': u'Ongerijmd',
+ 'th': u'บอร์ด',
+ 'zh-hk': u'詞意分道',
+ 'zh-tw': u'詞意分道'
+ }
- self.namespaces[29] = {
- 'fi': u'Hihitys Hikipelistä',
- 'th': u'คุยเรื่องบอร์ด',
- 'zh-hk': u'詞意分道討論',
- 'zh-tw': u'詞意分道討論'
- }
+ self.namespaces[29] = {
+ 'fi': u'Hihitys Hikipelistä',
+ 'th': u'คุยเรื่องบอร์ด',
+ 'zh-hk': u'詞意分道討論',
+ 'zh-tw': u'詞意分道討論'
+ }
- self.namespaces[30] = {
- 'pt': u'Deslivros',
- 'th': u'ไร้ซอร์ซ',
- 'zh-hk': u'臺語',
- 'zh-tw': u'臺語'
- }
+ self.namespaces[30] = {
+ 'pt': u'Deslivros',
+ 'th': u'ไร้ซอร์ซ',
+ 'zh-hk': u'臺語',
+ 'zh-tw': u'臺語'
+ }
- self.namespaces[31] = {
- 'pt': u'Deslivros Discussão',
- 'th': u'คุยเรื่องไร้ซอร์ซ',
- 'zh-hk': u'臺語討論',
- 'zh-tw': u'臺語討論'
- }
+ self.namespaces[31] = {
+ 'pt': u'Deslivros Discussão',
+ 'th': u'คุยเรื่องไร้ซอร์ซ',
+ 'zh-hk': u'臺語討論',
+ 'zh-tw': u'臺語討論'
+ }
- self.namespaces[32] = {
- 'ja': u'Portal',
- 'pt': u'Desentrevistas',
- 'th': u'ไร้คำคม',
- 'zh-hk': u'香港語',
- 'zh-tw': u'香港語'
- }
+ self.namespaces[32] = {
+ 'ja': u'Portal',
+ 'pt': u'Desentrevistas',
+ 'th': u'ไร้คำคม',
+ 'zh-hk': u'香港語',
+ 'zh-tw': u'香港語'
+ }
- self.namespaces[33] = {
- 'ja': u'Portal talk',
- 'pt': u'Desentrevistas Discussão',
- 'th': u'คุยเรื่องไร้คำคม',
- 'zh-hk': u'香港語討論',
- 'zh-tw': u'香港語討論'
- }
+ self.namespaces[33] = {
+ 'ja': u'Portal talk',
+ 'pt': u'Desentrevistas Discussão',
+ 'th': u'คุยเรื่องไร้คำคม',
+ 'zh-hk': u'香港語討論',
+ 'zh-tw': u'香港語討論'
+ }
- self.namespaces[34] = {
- 'th': u'ไร้ภาพ',
- 'zh-hk': u'書面語',
- 'zh-tw': u'書面語'
- }
+ self.namespaces[34] = {
+ 'th': u'ไร้ภาพ',
+ 'zh-hk': u'書面語',
+ 'zh-tw': u'書面語'
+ }
- self.namespaces[35] = {
- 'th': u'คุยเรื่องไร้ภาพ',
- 'zh-hk': u'書面語討論',
- 'zh-tw': u'書面語討論'
- }
+ self.namespaces[35] = {
+ 'th': u'คุยเรื่องไร้ภาพ',
+ 'zh-hk': u'書面語討論',
+ 'zh-tw': u'書面語討論'
+ }
- self.namespaces[36] = {
- 'zh-hk': u'偽基書籍',
- 'zh-tw': u'偽基書籍'
- }
+ self.namespaces[36] = {
+ 'zh-hk': u'偽基書籍',
+ 'zh-tw': u'偽基書籍'
+ }
- self.namespaces[37] = {
- 'zh-hk': u'偽基書籍討論',
- 'zh-tw': u'偽基書籍討論'
- }
+ self.namespaces[37] = {
+ 'zh-hk': u'偽基書籍討論',
+ 'zh-tw': u'偽基書籍討論'
+ }
- self.namespaces[100] = {
- 'de': u'UnNews',
- 'nn': u'Ikkenytt',
- 'no': u'Ikkenytt',
- 'pl': u'Cytaty',
- 'sv': u'PsykNyheter',
- 'tr': u'YanSözlük'
- }
+ self.namespaces[100] = {
+ 'de': u'UnNews',
+ 'nn': u'Ikkenytt',
+ 'no': u'Ikkenytt',
+ 'pl': u'Cytaty',
+ 'sv': u'PsykNyheter',
+ 'tr': u'YanSözlük'
+ }
- self.namespaces[101] = {
- 'de': u'UnNews Diskussion',
- 'nn': u'Ikkenytt-diskusjon',
- 'no': u'Ikkenytt-diskusjon',
- 'pl': u'Dyskusja cytatów',
- 'sv': u'PsykNyheter diskussion',
- 'tr': u'YanSözlük tartışma'
- }
+ self.namespaces[101] = {
+ 'de': u'UnNews Diskussion',
+ 'nn': u'Ikkenytt-diskusjon',
+ 'no': u'Ikkenytt-diskusjon',
+ 'pl': u'Dyskusja cytatów',
+ 'sv': u'PsykNyheter diskussion',
+ 'tr': u'YanSözlük tartışma'
+ }
- self.namespaces[102] = {
- 'de': u'Undictionary',
- 'en': u'UnNews',
- 'ja': u'UnNews',
- 'nn': u'Ikktionary',
- 'no': u'Ikktionary',
- 'pl': u'NonNews',
- 'sv': u'Forum',
- 'tr': u'YanHaber',
- }
+ self.namespaces[102] = {
+ 'de': u'Undictionary',
+ 'en': u'UnNews',
+ 'ja': u'UnNews',
+ 'nn': u'Ikktionary',
+ 'no': u'Ikktionary',
+ 'pl': u'NonNews',
+ 'sv': u'Forum',
+ 'tr': u'YanHaber',
+ }
- self.namespaces[103] = {
- 'de': u'Undictionary Diskussion',
- 'en': u'UnNews talk',
- 'ja': u'UnNews talk',
- 'nn': u'Ikktionary-diskusjon',
- 'no': u'Ikktionary-diskusjon',
- 'pl': u'Dyskusja NonNews',
- 'sv': u'Forumdiskussion',
- 'tr': u'YanHaber tartışma'
- }
+ self.namespaces[103] = {
+ 'de': u'Undictionary Diskussion',
+ 'en': u'UnNews talk',
+ 'ja': u'UnNews talk',
+ 'nn': u'Ikktionary-diskusjon',
+ 'no': u'Ikktionary-diskusjon',
+ 'pl': u'Dyskusja NonNews',
+ 'sv': u'Forumdiskussion',
+ 'tr': u'YanHaber tartışma'
+ }
- self.namespaces[104] = {
- 'de': u'UnBooks',
- 'en': u'Undictionary',
- 'pl': u'Nonźródła',
- 'sv': u'Psyktionary'
- }
+ self.namespaces[104] = {
+ 'de': u'UnBooks',
+ 'en': u'Undictionary',
+ 'pl': u'Nonźródła',
+ 'sv': u'Psyktionary'
+ }
- self.namespaces[105] = {
- 'de': u'UnBooks Diskussion',
- 'en': u'Undictionary talk',
- 'pl': u'Dyskusja nonźródeł',
- 'sv': u'Psyktionary diskussion'
- }
+ self.namespaces[105] = {
+ 'de': u'UnBooks Diskussion',
+ 'en': u'Undictionary talk',
+ 'pl': u'Dyskusja nonźródeł',
+ 'sv': u'Psyktionary diskussion'
+ }
- self.namespaces[106] = {
- '_default':'',
- 'en': u'Game',
- 'ja': u'Game',
- 'pl': u'Słownik',
- 'pt': u'Desnotícias',
- 'sv': u'PsykCitat'
- }
+ self.namespaces[106] = {
+ '_default':'',
+ 'en': u'Game',
+ 'ja': u'Game',
+ 'pl': u'Słownik',
+ 'pt': u'Desnotícias',
+ 'sv': u'PsykCitat'
+ }
- self.namespaces[107] = {
- 'en': u'Game talk',
- 'ja': u'Game talk',
- 'pl': u'Dyskusja słownika',
- 'pt': u'Desnotícias Discussão',
- 'sv': u'PsykCitat diskussion'
- }
+ self.namespaces[107] = {
+ 'en': u'Game talk',
+ 'ja': u'Game talk',
+ 'pl': u'Dyskusja słownika',
+ 'pt': u'Desnotícias Discussão',
+ 'sv': u'PsykCitat diskussion'
+ }
- self.namespaces[108] = {
- 'en': u'Babel',
- 'pl': u'Gra',
- 'pt': u'Jogo',
- 'sv': u'Spel'
- }
+ self.namespaces[108] = {
+ 'en': u'Babel',
+ 'pl': u'Gra',
+ 'pt': u'Jogo',
+ 'sv': u'Spel'
+ }
- self.namespaces[109] = {
- 'en': u'Babel talk',
- 'pl': u'Dyskusja gry',
- 'pt': u'Jogo Discussão',
- 'sv': u'Speldiskussion'
- }
+ self.namespaces[109] = {
+ 'en': u'Babel talk',
+ 'pl': u'Dyskusja gry',
+ 'pt': u'Jogo Discussão',
+ 'sv': u'Speldiskussion'
+ }
- self.namespaces[110] = {
- 'ar': u'Forum',
- 'ast': u'Forum',
- 'ca': u'Forum',
- 'cs': u'Forum',
- 'da': u'Forum',
- 'de': u'Forum',
- 'el': u'Forum',
- 'en': u'Forum',
- 'eo': u'Forum',
- 'es': u'Forum',
- 'fr': u'Forum',
- 'he': u'Forum',
- 'id': u'Forum',
- 'it': u'Forum',
- 'ja': u'Forum',
- 'jv': u'Forum',
- 'la': u'Forum',
- 'nn': u'Forum',
- 'no': u'Forum',
- 'pl': u'Forum',
- 'pt': u'Descionário',
- 'ru': u'Форум',
- 'sk': u'Forum',
- 'su': u'Forum',
- 'sv': u'PsykBöcker',
- 'tr': u'Astroloji',
- 'yi': u'Forum',
- 'zh': u'Forum'
- }
+ self.namespaces[110] = {
+ 'ar': u'Forum',
+ 'ast': u'Forum',
+ 'ca': u'Forum',
+ 'cs': u'Forum',
+ 'da': u'Forum',
+ 'de': u'Forum',
+ 'el': u'Forum',
+ 'en': u'Forum',
+ 'eo': u'Forum',
+ 'es': u'Forum',
+ 'fr': u'Forum',
+ 'he': u'Forum',
+ 'id': u'Forum',
+ 'it': u'Forum',
+ 'ja': u'Forum',
+ 'jv': u'Forum',
+ 'la': u'Forum',
+ 'nn': u'Forum',
+ 'no': u'Forum',
+ 'pl': u'Forum',
+ 'pt': u'Descionário',
+ 'ru': u'Форум',
+ 'sk': u'Forum',
+ 'su': u'Forum',
+ 'sv': u'PsykBöcker',
+ 'tr': u'Astroloji',
+ 'yi': u'Forum',
+ 'zh': u'Forum'
+ }
- self.namespaces[111] = {
- 'ar': u'Forum talk',
- 'ast': u'Forum talk',
- 'ca': u'Forum talk',
- 'cs': u'Forum talk',
- 'da': u'Forumdiskussion',
- 'de': u'Forum talk',
- 'el': u'Forum talk',
- 'en': u'Forum talk',
- 'eo': u'Forum talk',
- 'es': u'Forum talk',
- 'fr': u'Discussion Forum',
- 'he': u'Forum talk',
- 'id': u'Forum talk',
- 'it': u'Forum talk',
- 'ja': u'Forum talk',
- 'jv': u'Forum talk',
- 'la': u'Forum talk',
- 'nn': u'Forum-diskusjon',
- 'no': u'Forum-diskusjon',
- 'pl': u'Dyskusja forum',
- 'pt': u'Descionário Discussão',
- 'ru': u'Обсуждение форума',
- 'sk': u'Forum talk',
- 'su': u'Forum talk',
- 'sv': u'PsykBöckerdiskussion',
- 'tr': u'Astroloji tartışma',
- 'yi': u'Forum talk',
- 'zh': u'Forum talk'
- }
+ self.namespaces[111] = {
+ 'ar': u'Forum talk',
+ 'ast': u'Forum talk',
+ 'ca': u'Forum talk',
+ 'cs': u'Forum talk',
+ 'da': u'Forumdiskussion',
+ 'de': u'Forum talk',
+ 'el': u'Forum talk',
+ 'en': u'Forum talk',
+ 'eo': u'Forum talk',
+ 'es': u'Forum talk',
+ 'fr': u'Discussion Forum',
+ 'he': u'Forum talk',
+ 'id': u'Forum talk',
+ 'it': u'Forum talk',
+ 'ja': u'Forum talk',
+ 'jv': u'Forum talk',
+ 'la': u'Forum talk',
+ 'nn': u'Forum-diskusjon',
+ 'no': u'Forum-diskusjon',
+ 'pl': u'Dyskusja forum',
+ 'pt': u'Descionário Discussão',
+ 'ru': u'Обсуждение форума',
+ 'sk': u'Forum talk',
+ 'su': u'Forum talk',
+ 'sv': u'PsykBöckerdiskussion',
+ 'tr': u'Astroloji tartışma',
+ 'yi': u'Forum talk',
+ 'zh': u'Forum talk'
+ }
- self.namespaces[112] = {
- 'en': u'UnTunes',
- 'es': u'Incinoticias',
- 'fr': u'Désinformation',
- 'ja': u'UnTunes',
- 'nn': u'Hvordan',
- 'no': u'Hvordan',
- 'pl': u'Portal',
- 'tr': u'Forum'
- }
+ self.namespaces[112] = {
+ 'en': u'UnTunes',
+ 'es': u'Incinoticias',
+ 'fr': u'Désinformation',
+ 'ja': u'UnTunes',
+ 'nn': u'Hvordan',
+ 'no': u'Hvordan',
+ 'pl': u'Portal',
+ 'tr': u'Forum'
+ }
- self.namespaces[113] = {
- 'en': u'UnTunes talk',
- 'es': u'Incinoticias Discusión',
- 'fr': u'Discussion Désinformation',
- 'ja': u'UnTunes talk',
- 'no': u'Hvordan-diskusjon',
- 'pl': u'Dyskusja portalu',
- 'tr': u'Forum tartışma'
- }
+ self.namespaces[113] = {
+ 'en': u'UnTunes talk',
+ 'es': u'Incinoticias Discusión',
+ 'fr': u'Discussion Désinformation',
+ 'ja': u'UnTunes talk',
+ 'no': u'Hvordan-diskusjon',
+ 'pl': u'Dyskusja portalu',
+ 'tr': u'Forum tartışma'
+ }
- self.namespaces[114] = {
- 'es': u'Incitables',
- 'no': u'Hvorfor',
- 'pl': u'Poradnik'
- }
+ self.namespaces[114] = {
+ 'es': u'Incitables',
+ 'no': u'Hvorfor',
+ 'pl': u'Poradnik'
+ }
- self.namespaces[115] = {
- 'es': u'Incitables Discusión',
- 'no': u'Hvorfor-diskusjon',
- 'pl': u'Dyskusja poradnika'
- }
+ self.namespaces[115] = {
+ 'es': u'Incitables Discusión',
+ 'no': u'Hvorfor-diskusjon',
+ 'pl': u'Dyskusja poradnika'
+ }
- self.namespaces[120] = {
- 'pt': u'Privado',
- 'tr': u'YanMagazin'
- }
+ self.namespaces[120] = {
+ 'pt': u'Privado',
+ 'tr': u'YanMagazin'
+ }
- self.namespaces[121] = {
- 'pt': u'Privado Discussão',
- 'tr': u'YanMagazin tartışma'
- }
+ self.namespaces[121] = {
+ 'pt': u'Privado Discussão',
+ 'tr': u'YanMagazin tartışma'
+ }
- self.namespaces[122] = {
- 'pt': u'Regra'
- }
+ self.namespaces[122] = {
+ 'pt': u'Regra'
+ }
- self.namespaces[123] = {
- 'pt': u'Regra Discussão'
- }
+ self.namespaces[123] = {
+ 'pt': u'Regra Discussão'
+ }
- # A few selected big languages for things that we do not want to loop over
- # all languages. This is only needed by the titletranslate.py module, so
- # if you carefully avoid the options, you could get away without these
- # for another wiki family.
- self.languages_by_size = ['en', 'ja', 'pt', 'it',
'pl', 'fr', 'fi', 'es', 'zh-tw', 'de',
'no']
+ # A few selected big languages for things that we do not want to loop over
+ # all languages. This is only needed by the titletranslate.py module, so
+ # if you carefully avoid the options, you could get away without these
+ # for another wiki family.
+ self.languages_by_size = ['en', 'ja', 'pt', 'it',
'pl', 'fr', 'fi', 'es', 'zh-tw', 'de',
'no']
def hostname(self,code):
return self.langs[code]
Modified: trunk/pywikipedia/families/wikiversity_family.py
===================================================================
--- trunk/pywikipedia/families/wikiversity_family.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/families/wikiversity_family.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -56,7 +56,7 @@
'en': u'School',
'it': u'Facoltà',
'ja': u'School',
- 'cs': u'Fórum',
+ 'cs': u'Fórum',
}
self.namespaces[101] = {
'cs': u'Fórum diskuse',
@@ -64,7 +64,7 @@
'en': u'School talk',
'it': u'Discussioni facoltà',
'ja': u'School‐ノート',
- 'cs': u'Fórum diskuse',
+ 'cs': u'Fórum diskuse',
}
self.namespaces[102] = {
'el': u'Τμήμα',
Modified: trunk/pywikipedia/family.py
===================================================================
--- trunk/pywikipedia/family.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/family.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -2948,21 +2948,21 @@
# equivalent articles have identical titles among the group.
self.language_groups = {
# languages using the arabic script (incomplete)
- 'arab' : [
+ 'arab' : [
'ar', 'arz', 'ps', 'sd', 'ur',
# languages using multiple scripts, including arabic
- 'kk', 'ku', 'tt', 'ug'
+ 'kk', 'ku', 'tt', 'ug'
],
# languages that use chinese symbols
'chinese': [
'wuu', 'zh', 'zh-classical', 'zh-yue',
'gan', 'ii',
# languages using multiple/mixed scripts, including chinese
- 'ja', 'za'
+ 'ja', 'za'
],
# languages that use the cyrillic alphabet
'cyril': [
'ab', 'av', 'ba', 'be',
'be-x-old', 'bg', 'bxr', 'ce', 'cu', 'cv',
'kv',
- 'ky', 'mk', 'lbe', 'mdf', 'mn', 'mo',
'myv', 'os', 'ru', 'sah', 'tg',
+ 'ky', 'mk', 'lbe', 'mdf', 'mn',
'mo', 'myv', 'os', 'ru', 'sah', 'tg',
'tk', 'udm', 'uk', 'xal',
# languages using multiple scripts, including cyrillic
'ha', 'kk', 'sh', 'sr', 'tt'
@@ -2970,22 +2970,22 @@
# languages that use the latin alphabet
'latin': [
'aa', 'af', 'ak', 'als', 'an',
'ang', 'ast', 'ay', 'bar', 'bat-smg',
- 'bcl', 'bi', 'bm', 'br', 'bs', 'ca',
'cbk-zam', 'cdo', 'ceb', 'ch',
- 'cho', 'chy', 'co', 'crh', 'cs', 'csb',
'cy', 'da', 'de', 'diq', 'dsb',
- 'ee', 'eml', 'en', 'eo', 'es', 'et',
'eu', 'ext', 'ff', 'fi', 'fiu-vro',
- 'fj', 'fo', 'fr', 'frp', 'fur', 'fy',
'ga', 'gd', 'gl', 'gn', 'gv',
- 'hak', 'haw', 'hif', 'ho', 'hr', 'hsb',
'ht', 'hu', 'hz', 'ia', 'id',
- 'ie', 'ig', 'ik', 'ilo', 'io', 'is',
'it', 'jbo', 'jv', 'kaa', 'kab',
- 'kg', 'ki', 'kj', 'kl', 'kr', 'ksh',
'kw', 'la', 'lad', 'lb', 'lg',
- 'li', 'lij', 'lmo', 'ln', 'lt', 'lv',
'map-bms', 'mg', 'mh', 'mi', 'ms',
- 'mt', 'mus', 'na', 'nah', 'nap', 'nds',
'nds-nl', 'ng', 'nl', 'nn',
- 'no', 'nov', 'nrm', 'nv', 'ny', 'oc',
'om', 'pag', 'pam', 'pap', 'pdc',
- 'pih', 'pl', 'pms', 'pt', 'qu', 'rm',
'rn', 'ro', 'roa-rup', 'roa-tara',
+ 'bcl', 'bi', 'bm', 'br', 'bs',
'ca', 'cbk-zam', 'cdo', 'ceb', 'ch',
+ 'cho', 'chy', 'co', 'crh', 'cs',
'csb', 'cy', 'da', 'de', 'diq', 'dsb',
+ 'ee', 'eml', 'en', 'eo', 'es',
'et', 'eu', 'ext', 'ff', 'fi', 'fiu-vro',
+ 'fj', 'fo', 'fr', 'frp', 'fur',
'fy', 'ga', 'gd', 'gl', 'gn', 'gv',
+ 'hak', 'haw', 'hif', 'ho', 'hr',
'hsb', 'ht', 'hu', 'hz', 'ia', 'id',
+ 'ie', 'ig', 'ik', 'ilo', 'io',
'is', 'it', 'jbo', 'jv', 'kaa', 'kab',
+ 'kg', 'ki', 'kj', 'kl', 'kr',
'ksh', 'kw', 'la', 'lad', 'lb', 'lg',
+ 'li', 'lij', 'lmo', 'ln', 'lt',
'lv', 'map-bms', 'mg', 'mh', 'mi', 'ms',
+ 'mt', 'mus', 'na', 'nah', 'nap',
'nds', 'nds-nl', 'ng', 'nl', 'nn',
+ 'no', 'nov', 'nrm', 'nv', 'ny',
'oc', 'om', 'pag', 'pam', 'pap', 'pdc',
+ 'pih', 'pl', 'pms', 'pt', 'qu',
'rm', 'rn', 'ro', 'roa-rup', 'roa-tara',
'rw', 'sc', 'scn', 'sco', 'se',
'sg', 'simple', 'sk', 'sl', 'sm', 'sn',
- 'so', 'sq', 'srn', 'ss', 'st', 'stq',
'su', 'sv', 'sw', 'szl', 'tet',
- 'tl', 'tn', 'to', 'tpi', 'tr', 'ts',
'tum', 'tw', 'ty', 'uz', 've',
- 'vec', 'vi', 'vls', 'vo', 'wa', 'war',
'wo', 'xh', 'yo', 'zea',
- 'zh-min-nan', 'zu',
+ 'so', 'sq', 'srn', 'ss', 'st',
'stq', 'su', 'sv', 'sw', 'szl', 'tet',
+ 'tl', 'tn', 'to', 'tpi', 'tr',
'ts', 'tum', 'tw', 'ty', 'uz', 've',
+ 'vec', 'vi', 'vls', 'vo', 'wa',
'war', 'wo', 'xh', 'yo', 'zea',
+ 'zh-min-nan', 'zu',
# languages using multiple scripts, including latin
'az', 'chr', 'ha', 'iu', 'kk',
'ku', 'rmy', 'sh', 'sr', 'tt', 'ug',
'za'
],
Modified: trunk/pywikipedia/followlive.py
===================================================================
--- trunk/pywikipedia/followlive.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/followlive.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -286,7 +286,7 @@
'pos' : 'top'},
u'{{subst:Notchinese/auto}}':{
- 'msg' : u'機器人掛上模板: 本条目没有翻译',
+ 'msg' : u'機器人掛上模板: 本条目没有翻译',
'pos' : 'top'},
u'{{subst:Substub/auto}}' :{
Modified: trunk/pywikipedia/image.py
===================================================================
--- trunk/pywikipedia/image.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/image.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -45,7 +45,7 @@
"""
# Summary messages for replacing images
msg_replace={
- 'ar': u'روبوت - استبدال الصورة %s مع %s',
+ 'ar': u'روبوت - استبدال الصورة %s مع %s',
'de': u'Bot: Ersetze Bild %s durch %s',
'en': u'Robot - Replacing image %s with %s',
'es': u'Robot - Reemplazando imagen %s por %s',
@@ -65,7 +65,7 @@
# Summary messages for removing images
msg_remove={
- 'ar': u'روبوت - إزالة الصورة %s',
+ 'ar': u'روبوت - إزالة الصورة %s',
'de': u'Bot: Entferne Bild %s',
'en': u'Robot - Removing image %s',
'es': u'Robot - Retirando imagen %s',
Modified: trunk/pywikipedia/imagecopy.py
===================================================================
--- trunk/pywikipedia/imagecopy.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/imagecopy.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -220,7 +220,7 @@
imageMoveMessage = {
'_default': u'[[:File:%s|File]] moved to
[[:commons:Image:%s|commons]].',
- 'ar': u'[[:File:%s|الصورة]] تم نقلها إلى [[:commons:Image:%s|كومنز]].',
+ 'ar': u'[[:File:%s|الصورة]] تم نقلها إلى
[[:commons:Image:%s|كومنز]].',
'en': u'[[:File:%s|File]] moved to [[:commons:Image:%s|commons]].',
'hu': u'[[:File:%s|Kép]] átmozgatva a
[[:commons:Image:%s|Commons]]ba.',
'nl': u'[[:File:%s|Bestand]] is verplaatst naar
[[:commons:Image:%s|commons]].',
Modified: trunk/pywikipedia/inline_images.py
===================================================================
--- trunk/pywikipedia/inline_images.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/inline_images.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -35,7 +35,7 @@
msg = {
'en': u'This image was inline linked from %s. No information on author,
copyright status, or license is available.',
- 'ar': u'هذه الصورة كانت موصولة داخليا من %s. لا معلومات عن المؤلف، حالة حقوق
النشر، أو الترخيص متوفرة.',
+ 'ar': u'هذه الصورة كانت موصولة داخليا من %s. لا معلومات عن المؤلف، حالة
حقوق النشر، أو الترخيص متوفرة.',
'he': u'תמונה זו הייתה מקושרת מהדף %s. אין מידע זמין על המחבר, מצב זכויות
היוצרים או הרישיון.',
'pl': u'Obraz ten został dolinkowany z adresu %s. Brak jest informacji o
autorze, prawach autorskich czy licencji.',
'pt': u'Esta imagem foi inserida como linha de %s. Nenhum infomação sobre
autor, direitos autorais ou licença foi listada.',
Modified: trunk/pywikipedia/login.py
===================================================================
--- trunk/pywikipedia/login.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/login.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -30,7 +30,7 @@
-v -v Shows http requests made when logging in. This might leak
(doubly private data (password, session id), so make sure to check the
verbose) output. Using -log is recommended: this will output a lot of
- data
+ data
If not given as parameter, the script will ask for your username and password
(password entry will be hidden), log in to your home wiki using this
@@ -72,25 +72,25 @@
class LoginManager:
def __init__(self, password = None, sysop = False, site = None, username=None,
verbose=False):
self.site = site or wikipedia.getSite()
- if username:
- self.username=username
- # perform writeback.
- if site.family.name not in config.usernames:
- config.usernames[site.family.name]={}
- config.usernames[site.family.name][self.site.lang]=username
- else:
- if sysop:
- try:
- self.username = config.sysopnames[self.site.family.name][self.site.lang]
- except:
- raise wikipedia.NoUsername(u'ERROR: Sysop username for %s:%s is undefined.\nIf you
have a sysop account for that site, please add such a line to
user-config.py:\n\nsysopnames[\'%s\'][\'%s\'] =
\'myUsername\'' % (self.site.family.name, self.site.lang,
self.site.family.name, self.site.lang))
- else:
- try:
- self.username = config.usernames[self.site.family.name][self.site.lang]
- except:
- raise wikipedia.NoUsername(u'ERROR: Username for %s:%s is undefined.\nIf you have
an account for that site, please add such a line to
user-config.py:\n\nusernames[\'%s\'][\'%s\'] = \'myUsername\''
% (self.site.family.name, self.site.lang, self.site.family.name, self.site.lang))
+ if username:
+ self.username=username
+ # perform writeback.
+ if site.family.name not in config.usernames:
+ config.usernames[site.family.name]={}
+ config.usernames[site.family.name][self.site.lang]=username
+ else:
+ if sysop:
+ try:
+ self.username = config.sysopnames[self.site.family.name][self.site.lang]
+ except:
+ raise wikipedia.NoUsername(u'ERROR: Sysop username for %s:%s is
undefined.\nIf you have a sysop account for that site, please add such a line to
user-config.py:\n\nsysopnames[\'%s\'][\'%s\'] =
\'myUsername\'' % (self.site.family.name, self.site.lang,
self.site.family.name, self.site.lang))
+ else:
+ try:
+ self.username = config.usernames[self.site.family.name][self.site.lang]
+ except:
+ raise wikipedia.NoUsername(u'ERROR: Username for %s:%s is undefined.\nIf
you have an account for that site, please add such a line to
user-config.py:\n\nusernames[\'%s\'][\'%s\'] = \'myUsername\''
% (self.site.family.name, self.site.lang, self.site.family.name, self.site.lang))
self.password = password
- self.verbose = verbose
+ self.verbose = verbose
if getattr(config, 'password_file', ''):
self.readPassword()
@@ -142,35 +142,35 @@
login_address = self.site.login_address()
address = login_address + '&action=submit'
- if self.site.hostname() in config.authenticate.keys():
+ if self.site.hostname() in config.authenticate.keys():
headers = {
"Content-type": "application/x-www-form-urlencoded",
"User-agent": wikipedia.useragent
}
data = self.site.urlEncode(predata)
- if self.verbose:
- fakepredata = predata
- fakepredata['wpPassword'] = u'XXXX'
- wikipedia.output(u"urllib2.urlopen(urllib2.Request('%s', %s,
%s)):" % (self.site.protocol() + '://' + self.site.hostname() + address,
self.site.urlEncode(fakepredata), headers))
+ if self.verbose:
+ fakepredata = predata
+ fakepredata['wpPassword'] = u'XXXX'
+ wikipedia.output(u"urllib2.urlopen(urllib2.Request('%s', %s,
%s)):" % (self.site.protocol() + '://' + self.site.hostname() + address,
self.site.urlEncode(fakepredata), headers))
response = urllib2.urlopen(urllib2.Request(self.site.protocol() +
'://' + self.site.hostname() + address, data, headers))
data = response.read()
- if self.verbose:
+ if self.verbose:
fakedata = re.sub(r"(session|Token)=..........",
r"session=XXXXXXXXXX", data)
- trans = config.transliterate
- config.transliterate = False #transliteration breaks for some reason
+ trans = config.transliterate
+ config.transliterate = False #transliteration breaks for some reason
wikipedia.output(data.decode(self.site.encoding()))
- config.transliterate = trans
+ config.transliterate = trans
wikipedia.cj.save(wikipedia.COOKIEFILE)
return "Ok"
else:
response, data = self.site.postData(address, self.site.urlEncode(predata))
- if self.verbose:
- fakepredata = predata
- fakepredata['wpPassword'] = u'XXXXX'
- wikipedia.output(u"self.site.postData(%s, %s)" % (address,
self.site.urlEncode(fakepredata)))
- fakeresponsemsg = re.sub(r"(session|Token)=..........",
r"session=XXXXXXXXXX", response.msg.__str__())
- wikipedia.output(u"%s/%s\n%s" % (response.status, response.reason,
fakeresponsemsg))
- wikipedia.output(u"%s" % data)
+ if self.verbose:
+ fakepredata = predata
+ fakepredata['wpPassword'] = u'XXXXX'
+ wikipedia.output(u"self.site.postData(%s, %s)" % (address,
self.site.urlEncode(fakepredata)))
+ fakeresponsemsg = re.sub(r"(session|Token)=..........",
r"session=XXXXXXXXXX", response.msg.__str__())
+ wikipedia.output(u"%s/%s\n%s" % (response.status, response.reason,
fakeresponsemsg))
+ wikipedia.output(u"%s" % data)
Reat=re.compile(': (.*?);')
L = []
Modified: trunk/pywikipedia/logindata.py
===================================================================
--- trunk/pywikipedia/logindata.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/logindata.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -15,7 +15,7 @@
import sys, os
import settings
if settings.pywikipedia_path not in sys.path:
- sys.path.append(settings.pywikipedia_path)
+ sys.path.append(settings.pywikipedia_path)
# pywikipedia can only set itself up if everything is
# done in its own directory. This needs fixing sometime.
@@ -27,74 +27,74 @@
os.chdir(cwd)
class LoginData:
- """An example class that uses pywikipedia as a library.
- usage example:
-
- from logindata import LoginData, wikipedia
- target_wiki=LoginData( ... ) # for example, fill in from a settings file, or use code to
generate, or ...
- site=target_wiki.login()
- page=wikipedia.Page(site,"Main Page")
- """
+ """An example class that uses pywikipedia as a library.
+ usage example:
+
+ from logindata import LoginData, wikipedia
+ target_wiki=LoginData( ... ) # for example, fill in from a settings file, or use code
to generate, or ...
+ site=target_wiki.login()
+ page=wikipedia.Page(site,"Main Page")
+ """
- def __init__(
- """
- paramaters:
- name: arbitrary name. Pick something easy to remember
- protocol: http|https
- server: dns address or ip address
- scriptpath: path on server itself
- (ie: protocol:server/scriptpath
http://6.wikiation.nl/revisions/REL1.13.2)
- version: mediawiki version of the target mediawiki instance
- lang: default language, as configured on target mediawiki instance
- encoding: should (almost) always be utf-8
- api_supported: Does this mediawiki instance support the mediawiki api?
- RversionTab: Magic. See superclass for information.
- user: Username on wiki
- password: password for this user
- """
+ def __init__(
+ """
+ paramaters:
+ name: arbitrary name. Pick something easy to remember
+ protocol: http|https
+ server: dns address or ip address
+ scriptpath: path on server itself
+ (ie: protocol:server/scriptpath
http://6.wikiation.nl/revisions/REL1.13.2)
+ version: mediawiki version of the target mediawiki instance
+ lang: default language, as configured on target mediawiki instance
+ encoding: should (almost) always be utf-8
+ api_supported: Does this mediawiki instance support the mediawiki api?
+ RversionTab: Magic. See superclass for information.
+ user: Username on wiki
+ password: password for this user
+ """
- self,
- name='MY_NAME_FOR_THIS_SERVER',
- protocol='http',
- server='www.my_server.com',
- scriptpath='/my/script/path/',
- version='1.13.2',
- lang='en',
- encoding='utf-8',
- user='MY_BOT_USER',
- password='MY_SECRET_PASSWORD',
- RversionTab=None,
- api_supported=False
- ):
- self.lang=lang
- self.user=user
- self.password=password
- self.family=base_family.Family(
- name=name,
- protocol=protocol,
- server=server,
- scriptpath=scriptpath,
- version=version,
- lang=lang,
- encoding=encoding,
- RversionTab=RversionTab,
- api_supported=api_supported)
- self.site=None
-
- def login(self):
- """Attempt to log in on the site described
- by this class. Returns a pywikipedia site object"""
- self.site=wikipedia.Site(
- code=self.lang,
- fam=self.family,
- user=self.user
- )
- loginManager=login.LoginManager(
- password=self.password,
- site=self.site,
- username=self.user
- )
- loginManager.login()
- return self.site
+ self,
+ name='MY_NAME_FOR_THIS_SERVER',
+ protocol='http',
+ server='www.my_server.com',
+ scriptpath='/my/script/path/',
+ version='1.13.2',
+ lang='en',
+ encoding='utf-8',
+ user='MY_BOT_USER',
+ password='MY_SECRET_PASSWORD',
+ RversionTab=None,
+ api_supported=False
+ ):
+ self.lang=lang
+ self.user=user
+ self.password=password
+ self.family=base_family.Family(
+ name=name,
+ protocol=protocol,
+ server=server,
+ scriptpath=scriptpath,
+ version=version,
+ lang=lang,
+ encoding=encoding,
+ RversionTab=RversionTab,
+ api_supported=api_supported)
+ self.site=None
+
+ def login(self):
+ """Attempt to log in on the site described
+ by this class. Returns a pywikipedia site object"""
+ self.site=wikipedia.Site(
+ code=self.lang,
+ fam=self.family,
+ user=self.user
+ )
+ loginManager=login.LoginManager(
+ password=self.password,
+ site=self.site,
+ username=self.user
+ )
+ loginManager.login()
+ return self.site
Modified: trunk/pywikipedia/maintenance/preferences.py
===================================================================
--- trunk/pywikipedia/maintenance/preferences.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/maintenance/preferences.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -3,209 +3,209 @@
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)
-
+ 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)
+ 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) is Select:
- predata[key] = value.value
- elif type(value) is Checkbox:
- if value.state:
- 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 __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) is Select:
+ predata[key] = value.value
+ elif type(value) is Checkbox:
+ if value.state:
+ 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
-
+ 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, time
-
- log = open('preferences.txt', 'a')
- log.write('PREFERENCES\t%s\n' % time.gmtime())
- log.write('KEYS\t%s\n' % keys)
- log.write('VALUES\t%s\n' % values)
-
- for family in config.usernames:
- for lang in config.usernames[family]:
- try:
- set_for(lang, family, keys, values, verbose)
- except (SystemExit, KeyboardInterrupt):
- return
- except Exception, e:
- wikipedia.output(u'Warning! An exception occured! %s: %s' %
(e.__class__.__name__, str(e)))
- log.write('FAILED\t%s\t%s\n' % (family, lang))
- else:
- log.write('SUCCESS\t%s\t%s\n' % (family, lang))
- log.close()
-
+ import wikipedia, config, time
+
+ log = open('preferences.txt', 'a')
+ log.write('PREFERENCES\t%s\n' % time.gmtime())
+ log.write('KEYS\t%s\n' % keys)
+ log.write('VALUES\t%s\n' % values)
+
+ for family in config.usernames:
+ for lang in config.usernames[family]:
+ try:
+ set_for(lang, family, keys, values, verbose)
+ except (SystemExit, KeyboardInterrupt):
+ return
+ except Exception, e:
+ wikipedia.output(u'Warning! An exception occured! %s: %s' %
(e.__class__.__name__, str(e)))
+ log.write('FAILED\t%s\t%s\n' % (family, lang))
+ else:
+ log.write('SUCCESS\t%s\t%s\n' % (family, lang))
+ log.close()
+
def set_for(lang, family, keys, values, verbose = False):
- import wikipedia
- site = wikipedia.getSite(lang, family, 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()
- try:
- site.conn.close()
- except AttributeError:
- pass
-
+ import wikipedia
+ site = wikipedia.getSite(lang, family, 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()
+ try:
+ site.conn.close()
+ except AttributeError:
+ pass
+
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.' % \
- sum([len(family) for family in 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.")
-
+ import wikipedia, config
+
+ wikipedia.output(u'Warning! This script will set preferences on all configured
accounts!')
+ wikipedia.output(u'You have %s accounts configured.' % \
+ sum([len(family) for family in 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()
+ import sys
+ sys.path.append('..')
+ import wikipedia
+ try:
+ wikipedia.handleArgs()
+ main()
+ finally:
+ wikipedia.stopme()
Modified: trunk/pywikipedia/maintenance/setmail.py
===================================================================
--- trunk/pywikipedia/maintenance/setmail.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/maintenance/setmail.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -10,54 +10,54 @@
import urllib2
def confirm(link):
- req = urllib2.Request(link, headers = {'User-Agent': wikipedia.useragent})
- u = urllib2.urlopen(req)
- u.close()
+ req = urllib2.Request(link, headers = {'User-Agent': wikipedia.useragent})
+ u = urllib2.urlopen(req)
+ u.close()
if __name__ == '__main__':
- r_mail = re.compile(ur'(http\:\/\/\S*Confirmemail\S*)')
-
- email = wikipedia.input('Email?')
- host = wikipedia.input('Host?')
- port = wikipedia.input('Port (default: 110; ssl: 995)?')
- try:
- port = int(port)
- except ValueError:
- port = 0
- if not port:
- port = 110
- ssl = wikipedia.inputChoice('SSL? ', ['no', 'yes'],
- ['n', 'y'], (port == 995) and 'y' or 'n') ==
'y'
- username = wikipedia.input('User?')
- password = wikipedia.input('Password?', True)
- do_delete = wikipedia.inputChoice('Delete confirmed mails?', ['yes',
'no'], ['y', 'n'], 'y') == 'y'
-
- if email:
- preferences.set_all(['wpUserEmail', 'wpEmailFlag',
'wpOpenotifusertalkpages'],
- [email, True, False], verbose = True)
-
- if ssl:
- pop = poplib.POP3_SSL(host, port)
- else:
- pop = poplib.POP3(host, port)
-
- pop.user(username)
- pop.pass_(password)
- wikipedia.output(unicode(pop.getwelcome()))
- messages = [i.split(' ', 1)[0] for i in pop.list()[1]]
- for i in messages:
- msg = pop.retr(i)
- confirmed = False
- for line in msg[1]:
- if r_mail.search(line):
- confirmed = True
- link = r_mail.search(line).group(1)
- wikipedia.output(u'Confirming %s.' % link)
- confirm(link)
-
- if not confirmed:
- wikipedia.output(u'Unconfirmed mail!')
- elif do_delete:
- pop.dele(i)
- pop.quit()
-
+ r_mail = re.compile(ur'(http\:\/\/\S*Confirmemail\S*)')
+
+ email = wikipedia.input('Email?')
+ host = wikipedia.input('Host?')
+ port = wikipedia.input('Port (default: 110; ssl: 995)?')
+ try:
+ port = int(port)
+ except ValueError:
+ port = 0
+ if not port:
+ port = 110
+ ssl = wikipedia.inputChoice('SSL? ', ['no', 'yes'],
+ ['n', 'y'], (port == 995) and 'y' or 'n') ==
'y'
+ username = wikipedia.input('User?')
+ password = wikipedia.input('Password?', True)
+ do_delete = wikipedia.inputChoice('Delete confirmed mails?', ['yes',
'no'], ['y', 'n'], 'y') == 'y'
+
+ if email:
+ preferences.set_all(['wpUserEmail', 'wpEmailFlag',
'wpOpenotifusertalkpages'],
+ [email, True, False], verbose = True)
+
+ if ssl:
+ pop = poplib.POP3_SSL(host, port)
+ else:
+ pop = poplib.POP3(host, port)
+
+ pop.user(username)
+ pop.pass_(password)
+ wikipedia.output(unicode(pop.getwelcome()))
+ messages = [i.split(' ', 1)[0] for i in pop.list()[1]]
+ for i in messages:
+ msg = pop.retr(i)
+ confirmed = False
+ for line in msg[1]:
+ if r_mail.search(line):
+ confirmed = True
+ link = r_mail.search(line).group(1)
+ wikipedia.output(u'Confirming %s.' % link)
+ confirm(link)
+
+ if not confirmed:
+ wikipedia.output(u'Unconfirmed mail!')
+ elif do_delete:
+ pop.dele(i)
+ pop.quit()
+
Modified: trunk/pywikipedia/maintenance/update_namespaces.py
===================================================================
--- trunk/pywikipedia/maintenance/update_namespaces.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/maintenance/update_namespaces.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -13,62 +13,62 @@
r_list = '\\[.*?\\]'
r_namespace_def =
re.compile(r'[\'"]([a-z_-]*)[\'"]\s*\:\s*((?:%s)|(?:%s))\s*,' %
(r_string, r_list))
def update_family(family, changes):
- global namespace_section_text, namespace_defs, new_defs
-
- output(u'Updating family %s' % family)
- family_file = open('../families/%s_family.py' % family.name, 'r')
- old_family_text = family_text = family_file.read()
- family_file.close()
-
- for lang, namespaces in changes.iteritems():
- for namespace_id, namespace_name, predefined_namespace in namespaces:
- output(u'Setting namespace[%s] for %s to %s' % (namespace_id, lang,
namespace_name))
-
- namespace_section = re.search(r_namespace_section % namespace_id, family_text)
- if not namespace_section:
- continue
- namespace_section_text = namespace_section.group(1)
- namespace_defs = dict([(match.group(1), match.group(2))
- for match in r_namespace_def.finditer(namespace_section_text)])
-
- if not namespace_defs.get(lang, '').startswith('['):
- output(u'Updating namespace[%s] to %s' % (namespace_id, namespace_name))
-
- namespace_defs[lang] = escape_string(namespace_name.encode('utf-8'))
- else:
- output(u'Namespace[%s] definition is a list; not updating.' % namespace_id)
-
- new_defs = namespace_defs.items()
- new_defs.sort(key = lambda x: x[0])
- new_text = '\n' + ''.join([12 * ' ' + "'%s':
%s,\n" % i for i in new_defs]) + ' ' * 8
- family_text = family_text.replace(namespace_section.group(1), new_text)
-
- if test_data(family_text):
- output(u'Saving to family file')
- family_file = open('../families/%s_family.py' % family.name, 'w')
- family_file.write(family_text)
- family_file.close()
- else:
- output(u'Warning! Syntax error!')
- output(family_text.decode('utf-8'))
-
+ global namespace_section_text, namespace_defs, new_defs
+
+ output(u'Updating family %s' % family)
+ family_file = open('../families/%s_family.py' % family.name, 'r')
+ old_family_text = family_text = family_file.read()
+ family_file.close()
+
+ for lang, namespaces in changes.iteritems():
+ for namespace_id, namespace_name, predefined_namespace in namespaces:
+ output(u'Setting namespace[%s] for %s to %s' % (namespace_id, lang,
namespace_name))
+
+ namespace_section = re.search(r_namespace_section % namespace_id,
family_text)
+ if not namespace_section:
+ continue
+ namespace_section_text = namespace_section.group(1)
+ namespace_defs = dict([(match.group(1), match.group(2))
+ for match in r_namespace_def.finditer(namespace_section_text)])
+
+ if not namespace_defs.get(lang, '').startswith('['):
+ output(u'Updating namespace[%s] to %s' % (namespace_id,
namespace_name))
+
+ namespace_defs[lang] =
escape_string(namespace_name.encode('utf-8'))
+ else:
+ output(u'Namespace[%s] definition is a list; not updating.' %
namespace_id)
+
+ new_defs = namespace_defs.items()
+ new_defs.sort(key = lambda x: x[0])
+ new_text = '\n' + ''.join([12 * ' ' +
"'%s': %s,\n" % i for i in new_defs]) + ' ' * 8
+ family_text = family_text.replace(namespace_section.group(1), new_text)
+
+ if test_data(family_text):
+ output(u'Saving to family file')
+ family_file = open('../families/%s_family.py' % family.name,
'w')
+ family_file.write(family_text)
+ family_file.close()
+ else:
+ output(u'Warning! Syntax error!')
+ output(family_text.decode('utf-8'))
+
def escape_string(string):
- return "u'%s'" % string.replace('\\',
'\\\\').replace("'", "\\'")
-
+ return "u'%s'" % string.replace('\\',
'\\\\').replace("'", "\\'")
+
def test_data(_test_data):
- try:
- exec _test_data
- except SyntaxError:
- return False
- except:
- return True
- return True
-
+ try:
+ exec _test_data
+ except SyntaxError:
+ return False
+ except:
+ return True
+ return True
+
if __name__ == '__main__':
- try:
- wikipedia.handleArgs()
- family = wikipedia.Family(wikipedia.default_family)
- result = family_check.check_family(family)
- update_family(family, result)
- finally:
- wikipedia.stopme()
\ No newline at end of file
+ try:
+ wikipedia.handleArgs()
+ family = wikipedia.Family(wikipedia.default_family)
+ result = family_check.check_family(family)
+ update_family(family, result)
+ finally:
+ wikipedia.stopme()
\ No newline at end of file
Modified: trunk/pywikipedia/misspelling.py
===================================================================
--- trunk/pywikipedia/misspelling.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/misspelling.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -52,7 +52,7 @@
}
msg = {
- 'ar': u'روبوت: إصلاح وصلة خاطئة إلى %s',
+ 'ar': u'روبوت: إصلاح وصلة خاطئة إلى %s',
'da': u'Omdirigeringer af fejlstavninger',
'de': u'Bot: korrigiere Link auf Falschschreibung: %s',
'en': u'Robot: Fixing misspelled link to %s',
Modified: trunk/pywikipedia/mysql_autoconnection.py
===================================================================
--- trunk/pywikipedia/mysql_autoconnection.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/mysql_autoconnection.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -15,148 +15,148 @@
import time
class Connection(object):
- """A wrapper to the MySQLdb database and cursor object.
- MySQL does not support cursors, so they can be safely wrapped
- into one object.
- """
- RECOVERABLE_ERRORS = (
- 1040, # Too many connections
- 1152, # Aborted connection
- 2002, # Connection error
- 2003, # Can't connect
- 2006, # Server gone
- 2013, # Server lost
- 2014, # Commands out of sync
- )
+ """A wrapper to the MySQLdb database and cursor object.
+ MySQL does not support cursors, so they can be safely wrapped
+ into one object.
+ """
+ RECOVERABLE_ERRORS = (
+ 1040, # Too many connections
+ 1152, # Aborted connection
+ 2002, # Connection error
+ 2003, # Can't connect
+ 2006, # Server gone
+ 2013, # Server lost
+ 2014, # Commands out of sync
+ )
- def __init__(self, retry_timeout = 60, max_retries = -1,
- callback = lambda *args: None, *conn_args, **conn_kwargs):
+ def __init__(self, retry_timeout = 60, max_retries = -1,
+ callback = lambda *args: None, *conn_args, **conn_kwargs):
- self.retry_timeout = retry_timeout
- self.max_retries = max_retries
- self.current_retry = 0
- self.callback = callback
+ self.retry_timeout = retry_timeout
+ self.max_retries = max_retries
+ self.current_retry = 0
+ self.callback = callback
- self.conn_args = conn_args
- self.conn_kwargs = conn_kwargs
+ self.conn_args = conn_args
+ self.conn_kwargs = conn_kwargs
- self.connected = False
- self.connect()
+ self.connected = False
+ self.connect()
- def wait(self):
- if self.current_retry > self.max_retries and self.max_retries != -1:
- raise RuntimeError('Maximum retries exceeded')
- if self.current_retry:
- self.callback(self)
- time.sleep(self.current_retry * self.retry_timeout)
- self.current_retry += 1
- def __call(self, (object, function_name), *args, **kwargs):
- try:
- return getattr(object, function_name)(*args, **kwargs)
- except MySQLdb.Error, e:
- if e[0] in self.RECOVERABLE_ERRORS:
- self.error = e
- self.connect()
- return getattr(self, function_name)(*args, **kwargs)
- else:
- raise
+ def wait(self):
+ if self.current_retry > self.max_retries and self.max_retries != -1:
+ raise RuntimeError('Maximum retries exceeded')
+ if self.current_retry:
+ self.callback(self)
+ time.sleep(self.current_retry * self.retry_timeout)
+ self.current_retry += 1
+ def __call(self, (object, function_name), *args, **kwargs):
+ try:
+ return getattr(object, function_name)(*args, **kwargs)
+ except MySQLdb.Error, e:
+ if e[0] in self.RECOVERABLE_ERRORS:
+ self.error = e
+ self.connect()
+ return getattr(self, function_name)(*args, **kwargs)
+ else:
+ raise
- # Mimic database object
- def connect(self):
- self.close()
+ # Mimic database object
+ def connect(self):
+ self.close()
- while not self.connected:
- self.wait()
- try:
- self._connect()
- except MySQLdb.Error, e:
- self.error = e
- return True
+ while not self.connected:
+ self.wait()
+ try:
+ self._connect()
+ except MySQLdb.Error, e:
+ self.error = e
+ return True
- def _connect(self):
- self.database = MySQLdb.connect(*self.conn_args, **self.conn_kwargs)
- self.connected = True
- self.current_retry = 0
- self.__cursor = self.database.cursor()
+ def _connect(self):
+ self.database = MySQLdb.connect(*self.conn_args, **self.conn_kwargs)
+ self.connected = True
+ self.current_retry = 0
+ self.__cursor = self.database.cursor()
- def close(self):
- self.current_retry = 0
- self.connected = False
- try:
- self.database.close()
- except:
- pass
+ def close(self):
+ self.current_retry = 0
+ self.connected = False
+ try:
+ self.database.close()
+ except:
+ pass
- def cursor(self, cursorclass = MySQLdb.cursors.Cursor):
- if type(cursorclass) is not type(self.__cursor):
- self.__cursor = self.database.cursor(cursorclass)
- return self
+ def cursor(self, cursorclass = MySQLdb.cursors.Cursor):
+ if type(cursorclass) is not type(self.__cursor):
+ self.__cursor = self.database.cursor(cursorclass)
+ return self
- # Mimic cursor object
- def __iter__(self):
- return self.__cursor.__iter__()
- def __getattr__(self, name, *args, **kwargs):
- if hasattr(self.database, name):
- obj = self.database
- else:
- obj = self.__cursor
- attr = getattr(obj, name)
- if hasattr(attr, '__call__'):
- return CallWrapper(self.__call, (obj, name))
- return attr
+ # Mimic cursor object
+ def __iter__(self):
+ return self.__cursor.__iter__()
+ def __getattr__(self, name, *args, **kwargs):
+ if hasattr(self.database, name):
+ obj = self.database
+ else:
+ obj = self.__cursor
+ attr = getattr(obj, name)
+ if hasattr(attr, '__call__'):
+ return CallWrapper(self.__call, (obj, name))
+ return attr
class CallWrapper(object):
- def __init__(self, executor, function):
- self.__executor = executor
- self.__function = function
- def __call__(self, *args, **kwargs):
- return self.__executor(self.__function,
- *args, **kwargs)
- def __getattr__(self, name):
- getattr(self.__function, name)
+ def __init__(self, executor, function):
+ self.__executor = executor
+ self.__function = function
+ def __call__(self, *args, **kwargs):
+ return self.__executor(self.__function,
+ *args, **kwargs)
+ def __getattr__(self, name):
+ getattr(self.__function, name)
def connect(retry_timeout = 60, max_retries = -1,
- callback = lambda *args: None, *conn_args, **conn_kwargs):
+ callback = lambda *args: None, *conn_args, **conn_kwargs):
- return Connection(retry_timeout = retry_timeout,
- max_retries = max_retries,
- callback = callback,
- *conn_args, **conn_kwargs)
+ return Connection(retry_timeout = retry_timeout,
+ max_retries = max_retries,
+ callback = callback,
+ *conn_args, **conn_kwargs)
if __name__ == '__main__':
- def callback(conn):
- print 'Waiting for', conn
+ def callback(conn):
+ print 'Waiting for', conn
- host = raw_input('Host: ')
- username = raw_input('Username: ')
- password = raw_input('Password: ')
+ host = raw_input('Host: ')
+ username = raw_input('Username: ')
+ password = raw_input('Password: ')
- conn = connect(retry_timeout = 5, max_retries = 4, callback = callback,
- host = host, user = username, passwd = password, charset = 'utf8')
- cur = conn.cursor()
- print 'Connected!'
- conn.execute('SELECT 1')
- print 'Query ok, closing connection...'
- conn.close()
- conn.execute('SELECT 1')
- print 'Query ok, please kill the connection...'
- raw_input()
- conn.execute('SELECT 1')
- print 'Query ok!, please kill while connected...'
- raw_input()
- conn.execute('SELECT SLEEP(30), 1')
+ conn = connect(retry_timeout = 5, max_retries = 4, callback = callback,
+ host = host, user = username, passwd = password, charset = 'utf8')
+ cur = conn.cursor()
+ print 'Connected!'
+ conn.execute('SELECT 1')
+ print 'Query ok, closing connection...'
+ conn.close()
+ conn.execute('SELECT 1')
+ print 'Query ok, please kill the connection...'
+ raw_input()
+ conn.execute('SELECT 1')
+ print 'Query ok!, please kill while connected...'
+ raw_input()
+ conn.execute('SELECT SLEEP(30), 1')
- print 'Now testing inserts...'
- conn.execute('USE test')
- conn.execute('CREATE TEMPORARY TABLE mysql_autoconnection (value INT)')
- for i in xrange(10):
- conn.execute('INSERT INTO mysql_autoconnection VALUES (%s)', (i, ))
- conn.commit()
- conn.execute('SELECT * FROM mysql_autoconnection')
- print conn.fetchall()
- print 'Query ok!'
- raw_input()
+ print 'Now testing inserts...'
+ conn.execute('USE test')
+ conn.execute('CREATE TEMPORARY TABLE mysql_autoconnection (value INT)')
+ for i in xrange(10):
+ conn.execute('INSERT INTO mysql_autoconnection VALUES (%s)', (i, ))
+ conn.commit()
+ conn.execute('SELECT * FROM mysql_autoconnection')
+ print conn.fetchall()
+ print 'Query ok!'
+ raw_input()
Modified: trunk/pywikipedia/nowcommons.py
===================================================================
--- trunk/pywikipedia/nowcommons.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/nowcommons.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -87,7 +87,7 @@
'_default': [
u'NowCommons'
],
- 'ar': [
+ 'ar': [
u'الآن كومنز',
u'الآن كومونز',
],
Modified: trunk/pywikipedia/redirect.py
===================================================================
--- trunk/pywikipedia/redirect.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/redirect.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -305,7 +305,7 @@
site = wikipedia.getSite()
if namespaces == []:
namespaces = [ 0 ]
- maxurllen = 1018 # accomodate "GET " + apiQ + CR + LF in 1024 bytes.
+ maxurllen = 1018 # accomodate "GET " + apiQ + CR + LF in 1024
bytes.
apiQ = ''
for pageid in self.get_redirect_pageids_via_api(number = number, namespaces =
namespaces,
site = site, start = start, until = until ):
@@ -802,7 +802,7 @@
elif arg.startswith('-namespace:'):
ns = arg[11:]
if ns == '':
- ## "-namespace:" does NOT yield -namespace:0 further down the road!
+ ## "-namespace:" does NOT yield -namespace:0 further down the road!
ns = wikipedia.input(
u'Please enter a namespace by its number: ')
# u'Please enter a namespace by its name or number:
') TODO! at least for some generators.
Modified: trunk/pywikipedia/refcheck.py
===================================================================
--- trunk/pywikipedia/refcheck.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/refcheck.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -29,53 +29,53 @@
import re, sys, string
class ReferencesRobot:
- #def __init__(self):
- #Nothing
- def countRefs(self, templates, namespaces):
- mysite = wikipedia.getSite()
- finalText = [u'Number of transclusions per
template',u'------------------------------------']
- for template in templates:
- gen = pagegenerators.ReferringPageGenerator(wikipedia.Page(mysite,
mysite.template_namespace() + ':' + template), onlyTemplateInclusion = True)
- if namespaces:
- gen = pagegenerators.NamespaceFilterPageGenerator(gen, namespaces)
- count = 0
- for page in gen:
- count = count + 1
- finalText.append(u'%s: %d' % (template, count))
- for line in finalText:
- wikipedia.output(line)
+ #def __init__(self):
+ #Nothing
+ def countRefs(self, templates, namespaces):
+ mysite = wikipedia.getSite()
+ finalText = [u'Number of transclusions per
template',u'------------------------------------']
+ for template in templates:
+ gen = pagegenerators.ReferringPageGenerator(wikipedia.Page(mysite,
mysite.template_namespace() + ':' + template), onlyTemplateInclusion = True)
+ if namespaces:
+ gen = pagegenerators.NamespaceFilterPageGenerator(gen, namespaces)
+ count = 0
+ for page in gen:
+ count = count + 1
+ finalText.append(u'%s: %d' % (template, count))
+ for line in finalText:
+ wikipedia.output(line)
def main():
- doCount = False
- argsList = []
- namespaces = []
- #templates = ['ref', 'note', 'ref label', 'note label']
- for arg in wikipedia.handleArgs():
- if arg == '-count':
- doCount = True
- elif arg.startswith('-namespace:'):
- try:
- namespaces.append(int(arg[len('-namespace:'):]))
- except ValueError:
- namespaces.append(arg[len('-namespace:'):])
- else:
- argsList.append(arg)
+ doCount = False
+ argsList = []
+ namespaces = []
+ #templates = ['ref', 'note', 'ref label', 'note
label']
+ for arg in wikipedia.handleArgs():
+ if arg == '-count':
+ doCount = True
+ elif arg.startswith('-namespace:'):
+ try:
+ namespaces.append(int(arg[len('-namespace:'):]))
+ except ValueError:
+ namespaces.append(arg[len('-namespace:'):])
+ else:
+ argsList.append(arg)
- if doCount:
- robot = ReferencesRobot()
- if argsList:
- robot.countRefs(argsList, namespaces)
- else:
- robot.countRefs(['ref', 'note', 'ref label', 'note
label'], namespaces)
- else:
- wikipedia.showHelp('refcheck')
+ if doCount:
+ robot = ReferencesRobot()
+ if argsList:
+ robot.countRefs(argsList, namespaces)
+ else:
+ robot.countRefs(['ref', 'note', 'ref label',
'note label'], namespaces)
+ else:
+ wikipedia.showHelp('refcheck')
if __name__ == "__main__":
- try:
- main()
- finally:
- wikipedia.stopme()
+ try:
+ main()
+ finally:
+ wikipedia.stopme()
- #preloadingGen = pagegenerators.PreloadingGenerator(gen, pageNumber=100)
- #for page in preloadingGen:
- #pagetext = page.get()
+ #preloadingGen = pagegenerators.PreloadingGenerator(gen, pageNumber=100)
+ #for page in preloadingGen:
+ #pagetext = page.get()
Modified: trunk/pywikipedia/reflinks.py
===================================================================
--- trunk/pywikipedia/reflinks.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/reflinks.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -120,11 +120,11 @@
# Regex that match bare references
linksInRef = re.compile(
# bracketed URLs
- ur'(?i)<ref(?P<name>[^>]*)>\s*\[?(?P<url>(?:http|https|ftp)://(?:'
+
- # unbracketed with()
- ur'^\[\]\s<>"]+\([^\[\]\s<>"]+[^\[\]\s\.:;\\,<>\?"]+|'+
- # unbracketed without ()
- ur'[^\[\]\s<>"]+[^\[\]\s\)\.:;\\,<>\?"]+|[^\[\]\s<>"]+))[!?,\s]*\]?\s*</ref>')
+
ur'(?i)<ref(?P<name>[^>]*)>\s*\[?(?P<url>(?:http|https|ftp)://(?:'
+
+ # unbracketed with()
+
ur'^\[\]\s<>"]+\([^\[\]\s<>"]+[^\[\]\s\.:;\\,<>\?"]+|'+
+ # unbracketed without ()
+
ur'[^\[\]\s<>"]+[^\[\]\s\)\.:;\\,<>\?"]+|[^\[\]\s<>"]+))[!?,\s]*\]?\s*</ref>')
# Download this file :
#
http://www.twoevils.org/files/wikipedia/404-links.txt.gz
@@ -438,7 +438,7 @@
wikipedia.output( u'pdfinfo value error.' )
except OSError:
wikipedia.output( u'pdfinfo OS error.' )
- except: # Ignore errors
+ except: # Ignore errors
wikipedia.output( u'PDF processing error.' )
pass
finally:
@@ -516,7 +516,7 @@
wikipedia.output(u'\03{lightyellow}WARNING\03{default} :
Redirect to root : %s ' % ref.link)
continue
- # Read the first 1,000,000 bytes (0.95 MB)
+ # Read the first 1,000,000 bytes (0.95 MB)
linkedpagetext = f.read(1000000)
socket.setdefaulttimeout(None)
Modified: trunk/pywikipedia/simple_family.py
===================================================================
--- trunk/pywikipedia/simple_family.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/simple_family.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -13,86 +13,86 @@
import sys, settings
if settings.pywikipedia_path not in sys.path:
- sys.path.append(settings.pywikipedia_path)
+ sys.path.append(settings.pywikipedia_path)
import config, family, urllib
class Family(family.Family):
- """Friendlier version of the pywikipedia family class.
- We can use this in conjunction with none-pywikipedia
- config files.
-
- Note that this just handles most common cases.
- If you run into a special case, you'll have to fall back
- to your regular pywikipedia.
- """
-
- def __init__(self,
- """name: arbitrary name. Pick something easy to remember
- protocol: http|https
- server: dns address or ip address
- scriptpath: path on server itself
- (ie: protocol:server/scriptpath
http://6.wikiation.nl/revisions/REL1.13.2)
- version: mediawiki version of the target mediawiki instance
- lang: default language, as configured on target mediawiki instance
- encoding: should (almost) always be utf-8
- api_supported: Does this mediawiki instance support the mediawiki api?
- RversionTab: Magic. See superclass for information.
- """
- name='MY_NAME_FOR_THIS_SERVER',
- protocol='http',
- server='www.my_server.com',
- scriptpath='/my/script/path',
- version='1.13.2',
- lang='en',
- encoding='utf-8',
- api_supported=False,
- RversionTab=None # very rare beast, you probably won't need it.
- ):
+ """Friendlier version of the pywikipedia family class.
+ We can use this in conjunction with none-pywikipedia
+ config files.
+
+ Note that this just handles most common cases.
+ If you run into a special case, you'll have to fall back
+ to your regular pywikipedia.
+ """
+
+ def __init__(self,
+ """name: arbitrary name. Pick something easy to remember
+ protocol: http|https
+ server: dns address or ip address
+ scriptpath: path on server itself
+ (ie: protocol:server/scriptpath
http://6.wikiation.nl/revisions/REL1.13.2)
+ version: mediawiki version of the target mediawiki instance
+ lang: default language, as configured on target mediawiki instance
+ encoding: should (almost) always be utf-8
+ api_supported: Does this mediawiki instance support the mediawiki api?
+ RversionTab: Magic. See superclass for information.
+ """
+ name='MY_NAME_FOR_THIS_SERVER',
+ protocol='http',
+ server='www.my_server.com',
+ scriptpath='/my/script/path',
+ version='1.13.2',
+ lang='en',
+ encoding='utf-8',
+ api_supported=False,
+ RversionTab=None # very rare beast, you probably won't need it.
+ ):
- family.Family.__init__(self)
- self.name = name # REQUIRED; replace with actual name
+ family.Family.__init__(self)
+ self.name = name # REQUIRED; replace with actual name
- self.langs = { # REQUIRED
- lang: server, # Include one line for each wiki in family
- }
- self._protocol=protocol
- self._scriptpath=scriptpath
- self._version=version
- self._encoding=encoding
- # may as well add these here, so we can have a 1 stop shop
- self._lang=lang
- self._server=server
- self._api_supported=api_supported
- self._RversionTab=RversionTab
+ self.langs = { # REQUIRED
+ lang: server, # Include one line for each wiki in family
+ }
+ self._protocol=protocol
+ self._scriptpath=scriptpath
+ self._version=version
+ self._encoding=encoding
+ # may as well add these here, so we can have a 1 stop shop
+ self._lang=lang
+ self._server=server
+ self._api_supported=api_supported
+ self._RversionTab=RversionTab
- def protocol(self, code):
- """
- returns "http" or "https"
- """
- return self._protocol
+ def protocol(self, code):
+ """
+ returns "http" or "https"
+ """
+ return self._protocol
- def scriptpath(self, code):
- """returns the prefix used to locate scripts on this wiki.
- """
- return self._scriptpath
+ def scriptpath(self, code):
+ """returns the prefix used to locate scripts on this wiki.
+ """
+ return self._scriptpath
- def apipath(self, code):
- """returns whether or not this wiki
- if self._api_supported:
- return '%s/api.php' % self.scriptpath(code)
- else:
- raise NotImplementedError, "%s wiki family does not support api.php" %
self.name
+ def apipath(self, code):
+ """returns whether or not this wiki
+ if self._api_supported:
+ return '%s/api.php' % self.scriptpath(code)
+ else:
+ raise NotImplementedError, "%s wiki family does not support
api.php" % self.name
# Which version of MediaWiki is used?
- def version(self, code):
- # Replace with the actual version being run on your wiki
- return self._version
+ def version(self, code):
+ # Replace with the actual version being run on your wiki
+ return self._version
- def code2encoding(self, code):
- """Return the encoding for a specific language wiki"""
- # Most wikis nowadays use UTF-8, but change this if yours uses
- # a different encoding
- return self._encoding
+ def code2encoding(self, code):
+ """Return the encoding for a specific language
wiki"""
+ # Most wikis nowadays use UTF-8, but change this if yours uses
+ # a different encoding
+ return self._encoding
- def RversionTab(self, code):
- return self._RversionTab
+ def RversionTab(self, code):
+ return self._RversionTab
Modified: trunk/pywikipedia/speedy_delete.py
===================================================================
--- trunk/pywikipedia/speedy_delete.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/speedy_delete.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -83,7 +83,7 @@
# _default will be used if no such semantic template was used.
deletion_messages = {
'wikipedia':{
- 'ar': {
+ 'ar': {
u'_default': u'حذف مرشح للحذف السريع حسب [[ويكيبيديا:حذف
سريع|معايير الحذف السريع]]',
},
'de': {
Modified: trunk/pywikipedia/spellcheck.py
===================================================================
--- trunk/pywikipedia/spellcheck.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/spellcheck.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -35,7 +35,7 @@
on for example Japanese.
Command-line options:
--html change HTML-entities like ü into their respective letters.
+-html change HTML-entities like ü into their respective letters.
This is done both before and after the normal check.
-rebuild save the complete wordlist, not just the changes, removing the
old wordlist.
Modified: trunk/pywikipedia/standardize_notes.py
===================================================================
--- trunk/pywikipedia/standardize_notes.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/standardize_notes.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -377,7 +377,7 @@
wikipedia.output( u"Reading existing Notes section" )
self.doReadReferencesSection( new_text, refsectionname )
while self.references and self.references[len(self.references)-1] ==
u'\n':
- del self.references[len(self.references)-1] # delete trailing empty
lines
+ del self.references[len(self.references)-1] # delete trailing empty
lines
# Convert any external links to footnote references
wikipedia.output( u"Converting external links" )
new_text = self.doConvertExternalLinks( new_text )
@@ -400,7 +400,7 @@
Returns the text which is generated by converting external links to References.
Adds References to reference list.
"""
- new_text = '' # Default is no text
+ new_text = '' # Default is no text
skipsection = False
for text_line in original_text.splitlines(True): # Scan all text line by line
# Check for protected sections
@@ -408,63 +408,63 @@
# TODO: support subheadings within Notes section
# TODO: support Notes in alphabetic order
# TODO: support Notes in other orders
- if m: # if in a section, check if should skip this section
+ if m: # if in a section, check if should skip this section
if m.group('sectionname').lower().strip() in
referencesectionnames:
- skipsection = True # skipsection left True so no further links
converted
+ skipsection = True # skipsection left True so no further links
converted
if skipsection:
- new_text = new_text + text_line # skip section, so retain text.
+ new_text = new_text + text_line # skip section, so retain text.
else:
# TODO: recognize {{inline}} invisible footnotes when something can be
done with them
- #
- # Ignore lines within comments
- if not text_line.startswith( u'<!--' ):
- # Fix erroneous external links in double brackets
- Rextlink = re.compile(r'(?i)\[\[(?P<linkname>http://[^\]]+?)\]\]')
- # TODO: compiling the regex each time might be inefficient
- text_lineR = re.compile(Rextlink)
- MOextlink = text_lineR.search(text_line)
- while MOextlink: # find all links on line
- extlink_linkname = MOextlink.group('linkname')
- # Rewrite double brackets to single ones
- text_line=text_line[:MOextlink.start()] + '[%s]' % extlink_linkname +
text_line[MOextlink.end(0):]
- MOextlink = text_lineR.search(text_line,MOextlink.start(0)+1)
- # Regular expression to look for external link [linkname linktext] - linktext is
optional.
- # Also accepts erroneous pipe symbol as separator.
- # Accepts wikilinks within <linktext>
- #Rextlink = re.compile(r'[^\[]\[(?P<linkname>[h]*[ft]+tp:[^
[\]\|]+?)(?P<linktext>[ \|]+(( *[^\]\|]*)|( *\[\[.+?\]\])*)+)*\][^\]]')
- #Rextlink = re.compile(r'\[(?P<linkname>[h]*[ft]+tp:[^
[\]\|]+?)(?P<linktext>[ \|]+(( *[^\]\|]*)|( *\[\[.+?\]\])*)+)*\]')
- Rextlink = re.compile(r'(?i)\[(?P<linkname>[h]*[ft]+tp:[^
[\]\|]+?)(?P<linktext>[ \|]+(( *[^\]\|]*)|( *\[\[.+?\]\])*)+)*\]')
- # TODO: compiling the regex each time might be inefficient
- text_lineR = re.compile(Rextlink)
- MOextlink = text_lineR.search(text_line)
- while MOextlink: # find all links on line
- extlink_linkname = MOextlink.group('linkname')
- extlink_linktext = MOextlink.group('linktext')
- self.refsequence += 1
- ( refname, reftext ) = self.doConvertLinkTextToReference(self.refsequence,
extlink_linkname, extlink_linktext)
- self.references.append( reftext ) # append new entry to References
- if extlink_linktext:
- # If there was text as part of link, reinsert text before footnote.
- text_line=text_line[:MOextlink.start(0)] + '%s{{ref|%s}}' %
(extlink_linktext, refname) + text_line[MOextlink.end(0):]
- else:
- text_line=text_line[:MOextlink.start(0)] + '{{ref|%s}}' % refname +
text_line[MOextlink.end(0):]
- MOextlink = text_lineR.search(text_line,MOextlink.start(0)+1)
- # Search for {{doi}}
- Rdoi = re.compile(r'(?i){{doi\|(?P<doilink>[^}|]*)}}')
- # TODO: compiling the regex each time might be inefficient
- doiR = re.compile(Rdoi)
- MOdoi = doiR.search(text_line)
- while MOdoi: # find all doi on line
- doi_link = MOdoi.group('doilink')
- if doi_link:
- self.refsequence += 1
- ( refname, reftext ) = self.doConvertDOIToReference( self.refsequence, doi_link )
- self.references.append( reftext ) # append new entry to References
- text_line=text_line[:MOdoi.start(0)] + '{{ref|%s}}' % refname +
text_line[MOdoi.end(0):]
- MOdoi = doiR.search(text_line, MOdoi.start(0)+1)
- new_text = new_text + text_line # append new line to new text
+ #
+ # Ignore lines within comments
+ if not text_line.startswith( u'<!--' ):
+ # Fix erroneous external links in double brackets
+ Rextlink =
re.compile(r'(?i)\[\[(?P<linkname>http://[^\]]+?)\]\]')
+ # TODO: compiling the regex each time might be inefficient
+ text_lineR = re.compile(Rextlink)
+ MOextlink = text_lineR.search(text_line)
+ while MOextlink: # find all links on line
+ extlink_linkname = MOextlink.group('linkname')
+ # Rewrite double brackets to single ones
+ text_line=text_line[:MOextlink.start()] + '[%s]' %
extlink_linkname + text_line[MOextlink.end(0):]
+ MOextlink = text_lineR.search(text_line,MOextlink.start(0)+1)
+ # Regular expression to look for external link [linkname linktext] - linktext
is optional.
+ # Also accepts erroneous pipe symbol as separator.
+ # Accepts wikilinks within <linktext>
+ #Rextlink = re.compile(r'[^\[]\[(?P<linkname>[h]*[ft]+tp:[^
[\]\|]+?)(?P<linktext>[ \|]+(( *[^\]\|]*)|( *\[\[.+?\]\])*)+)*\][^\]]')
+ #Rextlink = re.compile(r'\[(?P<linkname>[h]*[ft]+tp:[^
[\]\|]+?)(?P<linktext>[ \|]+(( *[^\]\|]*)|( *\[\[.+?\]\])*)+)*\]')
+ Rextlink = re.compile(r'(?i)\[(?P<linkname>[h]*[ft]+tp:[^
[\]\|]+?)(?P<linktext>[ \|]+(( *[^\]\|]*)|( *\[\[.+?\]\])*)+)*\]')
+ # TODO: compiling the regex each time might be inefficient
+ text_lineR = re.compile(Rextlink)
+ MOextlink = text_lineR.search(text_line)
+ while MOextlink: # find all links on line
+ extlink_linkname = MOextlink.group('linkname')
+ extlink_linktext = MOextlink.group('linktext')
+ self.refsequence += 1
+ ( refname, reftext ) =
self.doConvertLinkTextToReference(self.refsequence, extlink_linkname, extlink_linktext)
+ self.references.append( reftext ) # append new entry to References
+ if extlink_linktext:
+ # If there was text as part of link, reinsert text before footnote.
+ text_line=text_line[:MOextlink.start(0)] + '%s{{ref|%s}}' %
(extlink_linktext, refname) + text_line[MOextlink.end(0):]
+ else:
+ text_line=text_line[:MOextlink.start(0)] + '{{ref|%s}}' % refname
+ text_line[MOextlink.end(0):]
+ MOextlink = text_lineR.search(text_line,MOextlink.start(0)+1)
+ # Search for {{doi}}
+ Rdoi = re.compile(r'(?i){{doi\|(?P<doilink>[^}|]*)}}')
+ # TODO: compiling the regex each time might be inefficient
+ doiR = re.compile(Rdoi)
+ MOdoi = doiR.search(text_line)
+ while MOdoi: # find all doi on line
+ doi_link = MOdoi.group('doilink')
+ if doi_link:
+ self.refsequence += 1
+ ( refname, reftext ) = self.doConvertDOIToReference( self.refsequence,
doi_link )
+ self.references.append( reftext ) # append new entry to
References
+ text_line=text_line[:MOdoi.start(0)] + '{{ref|%s}}' % refname +
text_line[MOdoi.end(0):]
+ MOdoi = doiR.search(text_line, MOdoi.start(0)+1)
+ new_text = new_text + text_line # append new line to new text
if new_text == '':
- new_text = original_text # If somehow no new text, return original text
+ new_text = original_text # If somehow no new text, return original text
return new_text
def doFindRefSection(self, original_text):
@@ -475,18 +475,18 @@
refsectionname = ''
sectionname = ''
for text_line in original_text.splitlines(True): # Scan all text line by line
- if refsectionname == '': # if ref section not found
+ if refsectionname == '': # if ref section not found
# Check if line has a section name
m = re.search( r'==+(?P<sectionname>[^=]+)==', text_line )
- if m: # if in a section, remember section name
+ if m: # if in a section, remember section name
sectionname = m.group('sectionname').strip()
wikipedia.output( u'Section: %s' % sectionname )
- else: # else not a section name so look for reference
+ else: # else not a section name so look for reference
n = re.search( r'(i?){{(note|ibid)[|]', text_line )
- if n: # if reference found
- refsectionname = sectionname # found reference section
+ if n: # if reference found
+ refsectionname = sectionname # found reference section
wikipedia.output( u'Ref section: %s' % refsectionname )
- break # stop looking
+ break # stop looking
return refsectionname
def doFindAllCitationSections(self, original_text, refsectionname):
@@ -499,10 +499,10 @@
for text_line in original_text.splitlines(True): # Scan all text line by line
# Check if line has a section name
m = re.search( "==[ ]*(?P<sectionname>[^=]+)[ ]*==",
text_line )
- if m: # if in a section, remember section name
+ if m: # if in a section, remember section name
sectionname = m.group('sectionname').strip()
if sectionname.lower().strip() in referencesectionnames:
- if sectionname not in refsectionlist: # if not already in list, add
to list.
+ if sectionname not in refsectionlist: # if not already in list,
add to list.
refsectionlist.extend( sectionname )
return refsectionlist
@@ -510,24 +510,24 @@
"""
Returns the text which is generated by rewriting references, including duplicate
refs.
"""
- new_text = '' # Default is no text
+ new_text = '' # Default is no text
skipsection = False
for text_line in original_text.splitlines(True): # Scan all text line by line
# Check for protected sections
m = re.search( r'==+(?P<sectionname>[^=]+)==', text_line )
- if m: # if in a section, check if should skip this section
- if refsectionname != '': # if a certain section name has been
identified
+ if m: # if in a section, check if should skip this section
+ if refsectionname != '': # if a certain section name has been
identified
m_section = m.group('sectionname')
wikipedia.output( u'Looking for "%s":
"%s"' % (refsectionname,unicode(m_section)) )
if unicode(m_section.strip()) == unicode(refsectionname):
wikipedia.output( u'Found Ref section.' )
- skipsection = True # skipsection left True so no further links
converted
- else: # else grab all possible sections
+ skipsection = True # skipsection left True so no further
links converted
+ else: # else grab all possible sections
if m.group('sectionname').lower().strip() in
referencesectionnames:
wikipedia.output( 'RefSection found by default names: %s'
% m.group('sectionname') )
- skipsection = True # skipsection left True so no further links
converted
+ skipsection = True # skipsection left True so no further
links converted
if skipsection:
- new_text = new_text + text_line # skip section, so retain text.
+ new_text = new_text + text_line # skip section, so retain text.
else:
# TODO: recognize {{inline}} invisible footnotes when something can be
done with them
#
@@ -537,26 +537,26 @@
Rtext_line =
re.compile(r'(?i){{(?P<reftype>ref|ref_num|ref_label)\|(?P<refname>[^}|]+?)}}')
m = Rtext_line.search( text_line )
alphabet26 = u'abcdefghijklmnopqrstuvwxyz'
- while m: # if found a reference
- if m.group('reftype').lower() in ( 'ref',
'ref_num', 'ref_label' ): # confirm ref
+ while m: # if found a reference
+ if m.group('reftype').lower() in ( 'ref',
'ref_num', 'ref_label' ): # confirm ref
refkey = m.group('refname').strip()
if refkey != '':
if refusage.has_key( refkey ):
# wikipedia.output( u'refusage[%s] = %s' %
(refkey,refusage[refkey]) )
- if refusage[refkey][2] == 0: # if first use of reference
+ if refusage[refkey][2] == 0: # if first use of
reference
text_line=text_line[:m.start(0)] +
'{{ref|%s}}' % (refkey) + text_line[m.end(0):]
- refusage[refkey][2] += 1 # count use of reference
- else: # else not first use of reference
+ refusage[refkey][2] += 1 # count use of reference
+ else: # else not first use of reference
text_line=text_line[:m.start(0)] +
'{{ref_label|%s|%d|%s}}' %
(refkey,(refusage[refkey][0])+1,alphabet26[((refusage[refkey][2])-1)%26]) +
text_line[m.end(0):]
- refusage[refkey][2] += 1 # count use of reference
+ refusage[refkey][2] += 1 # count use of reference
else:
# Odd, because refusage list is populated the key should
exist already.
- refusage[refkey] = [len(refusage),1,1] # remember this
reference
+ refusage[refkey] = [len(refusage),1,1] # remember this
reference
text_line=text_line[:m.start(0)] + '{{ref|%s}}' %
refkey + text_line[m.end(0):]
m = Rtext_line.search( text_line, m.start(0)+1 )
- new_text = new_text + text_line # append new line to new text
+ new_text = new_text + text_line # append new line to new text
if new_text == '':
- new_text = original_text # If somehow no new text, return original text
+ new_text = original_text # If somehow no new text, return original text
return new_text
def doGetTitleFromURL(self, extlink_linkname ):
@@ -569,24 +569,24 @@
urlfile = None
urlheaders = None
if len(extlink_linkname) > 5:
- socket.setdefaulttimeout( 20 ) # timeout in seconds
- wikipedia.get_throttle() # throttle down to Wikipedia rate
+ socket.setdefaulttimeout( 20 ) # timeout in seconds
+ wikipedia.get_throttle() # throttle down to Wikipedia rate
# Obey robots.txt restrictions
rp = robotparser.RobotFileParser()
rp.set_url( extlink_linkname )
try:
- rp.read() # read robots.txt
+ rp.read() # read robots.txt
except (IOError, socket.timeout):
wikipedia.output( u'Error accessing URL: %s' %
unicode(extlink_linkname) )
else:
urlobj = None
if not rp.can_fetch( "*", extlink_linkname ):
wikipedia.output( u'Robot prohibited: %s' %
unicode(extlink_linkname) )
- else: # else access allowed
+ else: # else access allowed
try:
if have_httpcache:
cache = HTTPCache( extlink_linkname )
- urlfile = cache.filename() # filename of cached date
+ urlfile = cache.filename() # filename of cached date
urlheaders = cache.info()
else:
(urlfile, urlheaders) = urllib.urlretrieve( extlink_linkname
)
@@ -596,7 +596,7 @@
wikipedia.output( u'Error %i accessing URL, %s. %s' %
(err, unicode(msg), unicode(extlink_linkname)) )
except socket.timeout, msg:
wikipedia.output( u'Error accessing URL, %s. %s' %
(unicode(msg), unicode(extlink_linkname)) )
- except: # Ignore other errors
+ except: # Ignore other errors
pass
if urlfile != None:
urlobj = open( urlfile )
@@ -619,7 +619,7 @@
wikipedia.output( u'pdfinfo value error.' )
except OSError:
wikipedia.output( u'pdfinfo OS error.' )
- except: # Ignore errors
+ except: # Ignore errors
wikipedia.output( u'PDF processing error.' )
pass
wikipedia.output( u'PDF done.' )
@@ -630,16 +630,16 @@
aline = urlobj.read()
maxalines = 100
while maxalines > 0 and aline and urltitle == '':
- maxalines -= 1 # reduce number of lines left to consider
+ maxalines -= 1 # reduce number of lines left to consider
titleRE =
re.search("(?i)<title>(?P<HTMLtitle>[^<>]+)", aline)
if titleRE:
try:
urltitle =
unicode(titleRE.group('HTMLtitle'), 'utf-8')
except:
- urltitle = u' ' # error, no title
- urltitle = u' '.join(urltitle.split()) # merge
whitespace
+ urltitle = u' ' # error, no title
+ urltitle = u' '.join(urltitle.split()) # merge
whitespace
wikipedia.output( u'::::Title: %s' % urltitle )
- break # found a title so stop looking
+ break # found a title so stop looking
else:
if maxalines < 1:
wikipedia.output( u'No title in URL. %s' %
unicode(extlink_linkname) )
@@ -658,7 +658,7 @@
urltitle = u''
try:
urltitle =
unicode(titleRE.group('HTMLtitle'), 'utf-8')
- urltitle = u'
'.join(urltitle.split()) # merge whitespace
+ urltitle = u'
'.join(urltitle.split()) # merge whitespace
wikipedia.output( u'::::Title:
%s' % urltitle )
except:
aline = urlobj.read()
@@ -666,7 +666,7 @@
else:
aline = urlobj.read()
continue
- break # found a title so stop looking
+ break # found a title so stop looking
else:
aline = urlobj.read()
else:
@@ -703,7 +703,7 @@
### wikipedia.output( unicode(text_token) )
else:
wikipedia.output( u'No data retrieved.' )
- socket.setdefaulttimeout( 200 ) # timeout in seconds
+ socket.setdefaulttimeout( 200 ) # timeout in seconds
urltitle = urltitle.replace(u'|',u':')
return urltitle.strip()
@@ -715,7 +715,7 @@
refname = u'refbot.%d' % refsequence
m = re.search("[\w]+://([\w]\.)*(?P<siteend>[\w.]+)[/\Z]",
extlink_linkname)
if m:
- refname = m.group('siteend') + u'.%d' % refsequence # use end
of site URL as reference name
+ refname = m.group('siteend') + u'.%d' % refsequence # use
end of site URL as reference name
new_text = u'# {{note|%s}} %s' % (refname, self.doConvertRefToCitation(
extlink_linktext, extlink_linkname, refname ) ) + '\n'
return (refname, new_text)
@@ -727,29 +727,29 @@
now = date.today()
if extlink_linktext == None or len(extlink_linktext.strip()) < 20:
wikipedia.output( u'Fetching URL: %s' % unicode(extlink_linkname) )
- urltitle = self.doGetTitleFromURL( extlink_linkname ) # try to get title from
URL
+ urltitle = self.doGetTitleFromURL( extlink_linkname ) # try to get title
from URL
if urltitle == None or urltitle == '':
- urltitle = extlink_linkname # Assume linkname for title
+ urltitle = extlink_linkname # Assume linkname for title
wikipedia.output( u'Title is: %s' % urltitle )
extlink_linktext = urltitle
- for newref in self.references: # scan through all references
- if extlink_linkname in newref: # if undescribed linkname same as a
previous entry
+ for newref in self.references: # scan through all references
+ if extlink_linkname in newref: # if undescribed linkname same as a
previous entry
if urltitle:
extlink_linktext = urltitle + ' (See above)'
else:
extlink_linktext = extlink_linkname + ' (See above)'
- break # found a matching previous linkname so stop looking
+ break # found a matching previous linkname so stop looking
if extlink_linktext == None or len(extlink_linktext) < 20:
exlink_linktext = urltitle
- # Look for a news web site
+ # Look for a news web site
for (sitename, newscompany, stripprefix) in newssites:
- if refname.startswith( sitename ):
- # If there is a prefix to strip from the title
+ if refname.startswith( sitename ):
+ # If there is a prefix to strip from the title
if stripprefix and extlink_linktext.startswith( stripprefix ):
- extlink_linktext = extlink_linktext[len(stripprefix):]
- new_text = u'{{news reference | title=%s | url=%s | urldate=%s | org=%s
}}' % ( extlink_linktext, extlink_linkname, now.isoformat(), newscompany ) +
'\n'
- break
- else: # else no special site found
+ extlink_linktext = extlink_linktext[len(stripprefix):]
+ new_text = u'{{news reference | title=%s | url=%s | urldate=%s | org=%s
}}' % ( extlink_linktext, extlink_linkname, now.isoformat(), newscompany ) +
'\n'
+ break
+ else: # else no special site found
new_text = u'{{web reference | title=%s | url=%s | date=%s }}' % (
extlink_linktext, extlink_linkname, now.isoformat() )
return (new_text)
@@ -762,9 +762,9 @@
urltitle = self.doGetTitleFromURL( 'http://dx.doi.org/' + doi_linktext )
# try to get title from URL
refname = 'refbot%d' % refsequence
if urltitle:
- new_text = '# {{note|%s}} %s {{doi|%s}}' % (refname, urltitle, doi_linktext)
+ '\n'
+ new_text = '# {{note|%s}} %s {{doi|%s}}' % (refname, urltitle,
doi_linktext) + '\n'
else:
- new_text = '# {{note|%s}} {{doi|%s}}' % (refname, doi_linktext) +
'\n'
+ new_text = '# {{note|%s}} {{doi|%s}}' % (refname, doi_linktext) +
'\n'
return (refname, new_text)
def doBuildSequenceListOfReferences(self, original_text):
@@ -772,21 +772,21 @@
Returns a list with all found references and sequence numbers.
"""
duplicatefound = False
- refusage = {} # Nothing found yet
+ refusage = {} # Nothing found yet
# Data structure: refusage[reference_key] = [ sequence_in_document, count,
count_during_dup_handling ]
for text_line in original_text.splitlines(True): # Scan all text line by line
# Check for various references
Rtext_line =
re.compile(r'(?i){{(?P<reftype>ref|ref_num|ref_label)\|(?P<refname>[^}|]+?)}}')
m = Rtext_line.search( text_line )
- while m: # if found a reference
- if m.group('reftype').lower() in ( 'ref',
'ref_num', 'ref_label' ): # confirm ref
+ while m: # if found a reference
+ if m.group('reftype').lower() in ( 'ref',
'ref_num', 'ref_label' ): # confirm ref
refkey = m.group('refname').strip()
if refkey != '':
if refusage.has_key(refkey):
- refusage[refkey][1] += 1 # duplicate use of reference
+ refusage[refkey][1] += 1 # duplicate use of reference
duplicatefound = True
else:
- refusage[refkey] = [len(refusage),0,0] # remember this
reference
+ refusage[refkey] = [len(refusage),0,0] # remember this
reference
m = Rtext_line.search( text_line, m.end() )
wikipedia.output( u'Number of refs: %d' % (len(refusage)) )
return (duplicatefound, refusage)
@@ -798,42 +798,42 @@
Contents of all Notes sections will be read.
"""
# TODO: support subsections within Notes
- new_text = '' # Default is no text
+ new_text = '' # Default is no text
intargetsection = False
for text_line in original_text.splitlines(True): # Scan all text line by line
# Check for target section
m = re.search( r'==+(?P<sectionname>[^=]+)==', text_line )
- if m: # if in a section, check if Notes section
- if refsectionname != '': # if a certain section name has been
identified
+ if m: # if in a section, check if Notes section
+ if refsectionname != '': # if a certain section name has been
identified
m_section = m.group('sectionname')
wikipedia.output( u'Looking for "%s":
"%s"' % (refsectionname,m_section) )
if unicode(m_section.strip()) == unicode(refsectionname):
wikipedia.output( u'Read Ref section.' )
- intargetsection = True # flag as being in section
+ intargetsection = True # flag as being in section
new_text = new_text + text_line
else:
- intargetsection = False # flag as not being in section
- else: # else grab all possible sections
+ intargetsection = False # flag as not being in
section
+ else: # else grab all possible sections
if m.group('sectionname').lower().strip() in
referencesectionnames:
- intargetsection = True # flag as being in section
+ intargetsection = True # flag as being in section
new_text = new_text + text_line
else:
- intargetsection = False # flag as not being in section
+ intargetsection = False # flag as not being in
section
else:
- if intargetsection: # if inside target section, remember this reference
line
+ if intargetsection: # if inside target section, remember this
reference line
if text_line.strip() != '':
- if text_line.lstrip()[0] in u'[{': # if line starts with
non-Ref WikiSyntax
- intargetsection = False # flag as not being in section
+ if text_line.lstrip()[0] in u'[{': # if line starts
with non-Ref WikiSyntax
+ intargetsection = False # flag as not being in
section
# TODO: need better way to handle special cases at end of refs
- if text_line.strip() == u'<!--READ ME!! PLEASE DO NOT JUST
ADD NEW NOTES AT THE BOTTOM. See the instructions above on ordering. -->': # This
line ends some Notes sections
- intargetsection = False # flag as not being in section
- if text_line.strip() == u'</div>': # This line ends
some Notes sections
- intargetsection = False # flag as not being in section
- if intargetsection: # if still inside target section
+ if text_line.strip() == u'<!--READ ME!! PLEASE DO NOT JUST
ADD NEW NOTES AT THE BOTTOM. See the instructions above on ordering. -->': #
This line ends some Notes sections
+ intargetsection = False # flag as not being in
section
+ if text_line.strip() == u'</div>': # This line
ends some Notes sections
+ intargetsection = False # flag as not being in
section
+ if intargetsection: # if still inside target section
# Convert any # wiki list to *; will be converted later if a
reference
if text_line[0] == '#':
- text_line = '*' + text_line[1:] # replace # with *
wiki
- self.references.append( text_line.rstrip() + u'\n' ) #
Append line to references
+ text_line = '*' + text_line[1:] # replace # with *
wiki
+ self.references.append( text_line.rstrip() + u'\n' ) #
Append line to references
new_text = new_text + text_line.rstrip() + u'\n'
return new_text
@@ -846,21 +846,21 @@
newreferences = references
if references != [] and refusage != {}:
newreferences = []
- for i in range(len(references)): # move nonrefs to top of list
+ for i in range(len(references)): # move nonrefs to top of list
text_line = references[i]
# TODO: compile search?
m =
re.search(r'(?i)[*#][\s]*{{(?P<reftype>note)\|(?P<refname>[^}|]+?)}}',
text_line)
# Special test to ignore Footnote instructions comment.
text_line_stripped = text_line.strip()
- if text_line_stripped.startswith(u'4) Add ') or not m: # if no
ref found
- newreferences.append(text_line) # add nonref to new list
+ if text_line_stripped.startswith(u'4) Add ') or not m: # if no
ref found
+ newreferences.append(text_line) # add nonref to new list
references[i] = None
refsort = {}
- for refkey in refusage.keys(): # build list of keys in document order
- refsort[ refusage[refkey][0] ] = refkey # refsort contains reference key
names
+ for refkey in refusage.keys(): # build list of keys in document order
+ refsort[ refusage[refkey][0] ] = refkey # refsort contains reference
key names
alphabet26 = u'abcdefghijklmnopqrstuvwxyz'
- for i in range(len(refsort)): # collect references in document order
- for search_num in range(len(references)): # find desired entry
+ for i in range(len(refsort)): # collect references in document order
+ for search_num in range(len(references)): # find desired entry
search_line = references[search_num]
if search_line:
# TODO: compile search?
@@ -868,17 +868,17 @@
m2 =
re.search(r'(?i)[*#]([\s]*{{(?P<reftype>note|note_label)\|(?P<refname>[^}|]+?)}})+',
search_line)
if m2:
refkey = m2.group('refname').strip()
- if refkey == refsort[i]: # if expected ref found
+ if refkey == refsort[i]: # if expected ref found
# Rewrite references
- note_text = '# {{note|%s}}' % refkey # rewrite
note tag
- if refusage[refkey][1] > 1: # if more than one
reference to citation
- for n in range(refusage[refkey][1]): # loop through
all repetitions
+ note_text = '# {{note|%s}}' % refkey # rewrite
note tag
+ if refusage[refkey][1] > 1: # if more than one
reference to citation
+ for n in range(refusage[refkey][1]): # loop
through all repetitions
note_text = note_text +
'{{note_label|%s|%d|%s}}' % (refkey,(refusage[refkey][0])+1,alphabet26[n%26])
search_line=search_line[:m2.start(0)] + note_text +
search_line[m2.end(0):]
- newreferences.append(search_line) # found, add entry
- del references[search_num] # delete used reference
- break # stop the search loop after entry found
- newreferences = newreferences + references # append any unused references
+ newreferences.append(search_line) # found, add entry
+ del references[search_num] # delete used
reference
+ break # stop the search loop after entry found
+ newreferences = newreferences + references # append any unused
references
return newreferences
def doUpdateReferencesSection(self, original_text, refusage, refsectionname):
@@ -886,79 +886,79 @@
Returns the text which is generated by rebuilding the Notes section.
Rewrite Notes section from references list.
"""
- new_text = '' # Default is no text
+ new_text = '' # Default is no text
intargetsection = False
for text_line in original_text.splitlines(True): # Scan all text line by line
# Check for target section
m = re.search( r'==+(?P<sectionname>[^=]+)==', text_line )
- if m: # if in a section, check if Notes section
- if refsectionname != '': # if a certain section name has been
identified
+ if m: # if in a section, check if Notes section
+ if refsectionname != '': # if a certain section name has been
identified
m_section = m.group('sectionname')
wikipedia.output( u'Looking for "%s":
"%s"' % (refsectionname,m_section) )
if unicode(m_section.strip()) == unicode(refsectionname):
wikipedia.output( u'Updating Ref section.' )
- intargetsection = True # flag as being in section
+ intargetsection = True # flag as being in section
else:
- intargetsection = False # flag as not being in section
- else: # else grab all possible sections
+ intargetsection = False # flag as not being in section
+ else: # else grab all possible sections
if m.group('sectionname').lower().strip() in
referencesectionnames:
- intargetsection = True # flag as being in section
+ intargetsection = True # flag as being in section
else:
- intargetsection = False # flag as not being in section
+ intargetsection = False # flag as not being in section
if intargetsection:
- new_text = new_text + text_line # append new line to new text
+ new_text = new_text + text_line # append new line to new text
if self.references != []:
- for newref in self.references: # scan through all references
+ for newref in self.references: # scan through all
references
if newref != None:
new_text = new_text + newref.rstrip() + u'\n'
# insert references
new_text = new_text + u'\n' # one trailing blank line
- self.references = [] # empty references
+ self.references = [] # empty references
else:
- new_text = new_text + text_line # copy section headline
+ new_text = new_text + text_line # copy section headline
else:
if intargetsection:
if text_line.strip() != '':
- if text_line.lstrip()[0] in u'[{': # if line starts with
non-Ref WikiSyntax
- intargetsection = False # flag as not being in section
+ if text_line.lstrip()[0] in u'[{': # if line starts
with non-Ref WikiSyntax
+ intargetsection = False # flag as not being in
section
# TODO: need better way to handle special cases at end of refs
- if text_line.strip() == u'<!--READ ME!! PLEASE DO NOT JUST
ADD NEW NOTES AT THE BOTTOM. See the instructions above on ordering. -->': # This
line ends some Notes sections
- intargetsection = False # flag as not being in section
- if text_line.strip() == u'</div>': # This line ends
some Notes sections
- intargetsection = False # flag as not being in section
- if not intargetsection: # if not in Notes section, remember line
- new_text = new_text + text_line # append new line to new text
+ if text_line.strip() == u'<!--READ ME!! PLEASE DO NOT JUST
ADD NEW NOTES AT THE BOTTOM. See the instructions above on ordering. -->': #
This line ends some Notes sections
+ intargetsection = False # flag as not being in
section
+ if text_line.strip() == u'</div>': # This line
ends some Notes sections
+ intargetsection = False # flag as not being in
section
+ if not intargetsection: # if not in Notes section, remember
line
+ new_text = new_text + text_line # append new line to new text
# If references list not emptied, there was no Notes section found
- if self.references != []: # empty references
+ if self.references != []: # empty references
# New Notes section needs to be created at bottom.
- text_line_counter = 0 # current line
- last_text_line_counter_value = 0 # number of last line of possible text
+ text_line_counter = 0 # current line
+ last_text_line_counter_value = 0 # number of last line of possible text
for text_line in original_text.splitlines(True): # Search for last normal
text line
- text_line_counter += 1 # count this line
+ text_line_counter += 1 # count this line
if text_line.strip() != '':
- if text_line.lstrip()[0].isalnum(): # if line starts with
alphanumeric
- last_text_line_counter = text_line_counter # number of last line
of possible text
+ if text_line.lstrip()[0].isalnum(): # if line starts with
alphanumeric
+ last_text_line_counter = text_line_counter # number of last
line of possible text
else:
- if text_line.lstrip()[0] in u'<=!|*#': # if line
starts with recognized wiki char
- if not text_line.startswith(u'<!--'): # if line
not start with a comment
- last_text_line_counter = text_line_counter # number of
last line of possible content
- new_text = '' # erase previous new_text
- text_line_counter = 0 # current line
+ if text_line.lstrip()[0] in u'<=!|*#': # if line
starts with recognized wiki char
+ if not text_line.startswith(u'<!--'): # if line
not start with a comment
+ last_text_line_counter = text_line_counter # number of
last line of possible content
+ new_text = '' # erase previous new_text
+ text_line_counter = 0 # current line
for text_line in original_text.splitlines(True): # Search for last normal
text line
- text_line_counter += 1 # count this line
- if last_text_line_counter == text_line_counter: # if found insertion
point
- new_text = new_text + text_line # append new line to new text
- new_text = new_text + '\n== Notes ==\n' # set to standard
name
+ text_line_counter += 1 # count this line
+ if last_text_line_counter == text_line_counter: # if found insertion
point
+ new_text = new_text + text_line # append new line to new text
+ new_text = new_text + '\n== Notes ==\n' # set to standard
name
new_text = new_text + u'{{subst:Footnote3text}}\n'
if self.references != []:
- for newref in self.references: # scan through all references
+ for newref in self.references: # scan through all
references
if newref is not None:
new_text = new_text + newref # insert references
new_text = new_text + u'\n' # one trailing blank line
- self.references = [] # empty references
+ self.references = [] # empty references
else:
- new_text = new_text + text_line # append new line to new text
+ new_text = new_text + text_line # append new line to new text
if new_text == '':
- new_text = original_text # If somehow no new text, return original text
+ new_text = original_text # If somehow no new text, return original text
return new_text
def run(self):
Modified: trunk/pywikipedia/template.py
===================================================================
--- trunk/pywikipedia/template.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/template.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -143,7 +143,7 @@
"""
# Summary messages for replacing templates
msg_change={
- 'ar':u'روبوت: تغيير القالب: %s',
+ 'ar':u'روبوت: تغيير القالب: %s',
'da':u'Bot: Erstatter skabelon: %s',
'de':u'Bot: Ändere Vorlage: %s',
'en':u'Robot: Changing template: %s',
@@ -167,7 +167,7 @@
#Needs more translations!
msgs_change={
- 'ar':u'روبوت: تغيير القوالب: %s',
+ 'ar':u'روبوت: تغيير القوالب: %s',
'da':u'Bot: Erstatter skabeloner: %s',
'de':u'Bot: Ändere Vorlagen: %s',
'en':u'Robot: Changing templates: %s',
@@ -188,7 +188,7 @@
# Summary messages for removing templates
msg_remove={
- 'ar':u'روبوت: إزالة القالب: %s',
+ 'ar':u'روبوت: إزالة القالب: %s',
'da':u'Bot: Fjerner skabelon: %s',
'de':u'Bot: Entferne Vorlage: %s',
'en':u'Robot: Removing template: %s',
@@ -212,7 +212,7 @@
#Needs more translations!
msgs_remove={
- 'ar':u'روبوت: إزالة القوالب: %s',
+ 'ar':u'روبوت: إزالة القوالب: %s',
'da':u'Bot: Fjerner skabeloner: %s',
'de':u'Bot: Entferne Vorlagen: %s',
'en':u'Robot: Removing templates: %s',
@@ -234,7 +234,7 @@
# Summary messages for substituting templates
#Needs more translations!
msg_subst={
- 'ar':u'روبوت: نسخ القالب: %s',
+ 'ar':u'روبوت: نسخ القالب: %s',
'da':u'Bot: Substituerer skabelon: %s',
'de':u'Bot: Umgehe Vorlage: %s',
'en':u'Robot: Substituting template: %s',
@@ -254,7 +254,7 @@
#Needs more translations!
msgs_subst={
- 'ar':u'روبوت: نسخ القوالب: %s',
+ 'ar':u'روبوت: نسخ القوالب: %s',
'da':u'Bot: Substituerer skabeloner: %s',
'de':u'Bot: Umgehe Vorlagen: %s',
'en':u'Robot: Substituting templates: %s',
Modified: trunk/pywikipedia/testfamily.py
===================================================================
--- trunk/pywikipedia/testfamily.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/testfamily.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -1,5 +1,5 @@
#!/usr/bin/python
-# -*- coding: utf-8 -*-
+# -*- coding: utf-8 -*-
"""
This utility's primary use is to find all mismatches between the namespace
naming in the family files and the language files on the wiki servers.
Modified: trunk/pywikipedia/us-states.py
===================================================================
--- trunk/pywikipedia/us-states.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/us-states.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -27,7 +27,7 @@
start = '0'
force = False
msg = {'en':'Creating state abbreviation redirect',
- 'ar':'إنشاء تحويلة اختصار الولاية',
+ 'ar':'إنشاء تحويلة اختصار الولاية',
'he':u'יוצר הפניה מראשי התיבות של המדינה',
}
Modified: trunk/pywikipedia/userinterfaces/terminal_interface.py
===================================================================
--- trunk/pywikipedia/userinterfaces/terminal_interface.py 2009-03-24 01:15:12 UTC (rev
6539)
+++ trunk/pywikipedia/userinterfaces/terminal_interface.py 2009-03-24 01:15:50 UTC (rev
6540)
@@ -263,7 +263,7 @@
answer = self.input(prompt)
if answer.lower() in hotkeys or answer.upper() in hotkeys:
return answer
- elif default and answer=='': # empty string entered
+ elif default and answer=='': # empty string entered
return default
def editText(self, text, jumpIndex = None, highlight = None):
Modified: trunk/pywikipedia/userlib.py
===================================================================
--- trunk/pywikipedia/userlib.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/userlib.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -67,7 +67,7 @@
def editedPages(self, limit=500):
""" Deprecated function that wraps 'contributions'
- for backwards compatibility
+ for backwards compatibility
"""
for page in self.contributions(limit):
yield page[0]
@@ -85,15 +85,15 @@
offset = 0
step = min(limit,500)
older_str = None
- try:
- older_str = self.site.mediawiki_message('pager-older-n')
- except wikipedia.KeyError:
- older_str = self.site.mediawiki_message('sp-contributions-older')
+ try:
+ older_str = self.site.mediawiki_message('pager-older-n')
+ except wikipedia.KeyError:
+ older_str = self.site.mediawiki_message('sp-contributions-older')
if older_str.startswith('{{PLURAL:$1'):
- older_str = older_str[13:]
- older_str = older_str[older_str.find('|')+1:]
- older_str = older_str[:-2]
- older_str = older_str.replace('$1',str(step))
+ older_str = older_str[13:]
+ older_str = older_str[older_str.find('|')+1:]
+ older_str = older_str[:-2]
+ older_str = older_str.replace('$1',str(step))
address = self.site.contribs_address(self.name,limit=step)
contribRX = re.compile('<li[^>]*> *<a
href="(?P<url>[^"]*?)"
title="[^"]+">(?P<date>[^<]+)</a>.*>diff</a>\)
*(<span class="[^"]+">[A-Za-z]</span>)* *<a
href="[^"]+" (class="[^"]+"
)?title="[^"]+">(?P<title>[^<]+)</a>
*(?P<comment>.*?)(?P<top><strong> *\(top\) *</strong>)? *(<span
class="mw-rollback-link">\[<a
href="[^"]+token=(?P<rollbackToken>[^"]+)%2B%5C".*rollback</a>\]</span>)?
*</li>')
Modified: trunk/pywikipedia/wikipedia.py
===================================================================
--- trunk/pywikipedia/wikipedia.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/wikipedia.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -773,7 +773,7 @@
retry_idle_time = 30
else:
output( u"Failed to access wiki")
- sys.exit(1)
+ sys.exit(1)
# Check for restrictions
m = re.search('var wgRestrictionEdit = \\["(\w+)"\\]', text)
if m:
@@ -4656,8 +4656,8 @@
Returns the HTML text of the page converted to unicode.
"""
- if retry==None:
- retry=config.retry_on_fail
+ if retry==None:
+ retry=config.retry_on_fail
if False: #self.persistent_http and not data:
self.conn.putrequest('GET', path)
@@ -4705,7 +4705,7 @@
while not retrieved:
try:
if self.hostname() in config.authenticate.keys():
- request = urllib2.Request(url, data)
+ request = urllib2.Request(url, data)
request.add_header('User-agent', useragent)
opener = urllib2.build_opener()
f = opener.open(request)
Modified: trunk/pywikipedia/wiktionary/entry.py
===================================================================
--- trunk/pywikipedia/wiktionary/entry.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/wiktionary/entry.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -17,11 +17,11 @@
""" Constructor
Called with one parameter:
- the language of this entry
- and can optionally be initialized with a first meaning
+ and can optionally be initialized with a first meaning
"""
self.entrylang=entrylang
self.meanings = {} # a dictionary containing the meanings for this term grouped
by part of speech
- if meaning:
+ if meaning:
self.addMeaning(meaning)
self.posorder = [] # we don't want to shuffle the order of the parts of
speech, so we keep a list to keep the order in which they were encountered
Modified: trunk/pywikipedia/wiktionary/meaning.py
===================================================================
--- trunk/pywikipedia/wiktionary/meaning.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/wiktionary/meaning.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -312,7 +312,7 @@
ready for Wiktionary
The behavior changes with the circumstances.
For an entry in the same language as the Wiktionary the full list of
translations is contained in the output, excluding the local
- language itself
+ language itself
- This list of translations has to end up in a table with two columns
- The first column of this table contains languages with names from A to M,
the second contains N to Z
- If a column in this list remains empty a html comment is put in that
column
Modified: trunk/pywikipedia/wiktionary/wiktionarypagetest.py
===================================================================
--- trunk/pywikipedia/wiktionary/wiktionarypagetest.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/wiktionary/wiktionarypagetest.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -199,8 +199,8 @@
}
}
},
- {'definition': u"A piece of metal, often [[hexagonal]], with a hole
through it with internal threading intended to fit on to a bolt.",
'concisedef': u'that fits on a bolt',
- 'trans': {'remark': '',
+ {'definition': u"A piece of metal, often [[hexagonal]], with a hole
through it with internal threading intended to fit on to a bolt.",
'concisedef': u'that fits on a bolt',
+ 'trans': {'remark': '',
'alltrans': {
'nl': {'remark': '',
'translations': [{'remark':
'',
@@ -370,18 +370,18 @@
# internalrepresentation=value['internalrep']
# apage =
wiktionarypage.WiktionaryPage(value['wikilang'],value['term'])
# apage.parseWikiPage(value['wikiformat'])
-#
+#
# self.assertEqual(apage.categories, internalrepresentation[0])
-#
+#
# def testWhetherLinksAreParsedProperly(self):
# """Test whether Links are parsed properly"""
# for value in self.knownvalues:
# internalrepresentation=value['internalrep']
# apage =
wiktionarypage.WiktionaryPage(value['wikilang'],value['term'])
# apage.parseWikiPage(value['wikiformat'])
-#
+#
# self.assertEqual(apage.interwikilinks, internalrepresentation[1])
-#
+#
# def testWhetherDefsAreParsedProperly(self):
# """Test whether definitions are parsed
properly"""
# for value in self.knownvalues:
@@ -396,14 +396,14 @@
# refdefs=[]
# for definition in definitions:
# refdefs.append(definition['definition'])
-#
+#
# resultmeanings=[]
# for key in apage.entries[entrylang].meanings.keys():
# for resultmeaning in apage.entries[entrylang].meanings[key]:
# resultmeanings.append(resultmeaning.definition)
-#
+#
# self.assertEqual(resultmeanings.sort(), refdefs.sort())
-#
+#
# def testWhetherDefsAndConciseDefsAreMatchedProperly(self):
# """Test whether definitions and concisedefs are matched
properly"""
# for value in self.knownvalues:
@@ -416,16 +416,16 @@
# for definition in definitions:
# if definition['concisedef']!='':
# refdefs[definition['concisedef']] =
definition['definition']
-#
+#
# resultmeanings={}
# for key in apage.entries[entrylang].meanings.keys():
# for resultmeaning in apage.entries[entrylang].meanings[key]:
# resultmeanings[resultmeaning.concisedef] =
resultmeaning.definition
-#
+#
# for concisedef in resultmeanings.keys():
# if concisedef!='' and refdefs.has_key(concisedef) and
resultmeanings.has_key(concisedef):
# self.assertEqual(resultmeanings[concisedef],
refdefs[concisedef])
-#
+#
# def testWhetherSynonymsAreParsedProperly(self):
# """Test whether synonyms are parsed properly"""
# for value in self.knownvalues:
@@ -438,16 +438,16 @@
# for definition in definitions:
# if definition.has_key('syns') and
definition['syns']!='':
# refsyns[definition['concisedef']] =
definition['syns']
-#
+#
# resultsyns={}
# for key in apage.entries[entrylang].meanings.keys():
# for resultmeaning in apage.entries[entrylang].meanings[key]:
# resultsyns[resultmeaning.concisedef] = resultmeaning.synonyms
-#
+#
# for concisedef in resultsyns.keys():
# if concisedef!='' and refsyns.has_key(concisedef) and
resultsyns.has_key(concisedef):
# self.assertEqual(resultsyns[concisedef], refsyns[concisedef])
-#
+#
def testWhetherTranslationsAreParsedProperly(self):
"""Test whether translations are parsed
properly"""
for value in self.knownvalues:
Modified: trunk/pywikipedia/wiktionary.py
===================================================================
--- trunk/pywikipedia/wiktionary.py 2009-03-24 01:15:12 UTC (rev 6539)
+++ trunk/pywikipedia/wiktionary.py 2009-03-24 01:15:50 UTC (rev 6540)
@@ -584,11 +584,11 @@
""" Constructor
Called with one parameter:
- the language of this entry
- and can optionally be initialized with a first meaning
+ and can optionally be initialized with a first meaning
"""
self.entrylang=entrylang
self.meanings = {} # a dictionary containing the meanings for this term grouped
by part of speech
- if meaning:
+ if meaning:
self.addMeaning(meaning)
self.posorder = [] # we don't want to shuffle the order of the parts of
speech, so we keep a list to keep the order in which they were encountered
@@ -804,7 +804,7 @@
ready for Wiktionary
The behavior changes with the circumstances.
For an entry in the same language as the Wiktionary the full list of
translations is contained in the output, excluding the local
- language itself
+ language itself
- This list of translations has to end up in a table with two columns
- The first column of this table contains languages with names from A to M,
the second contains N to Z
- If a column in this list remains empty a html comment is put in that
column