1 # python-simplemediawiki - Extremely low-level wrapper to the MediaWiki API
2 # Copyright (C) 2010 Red Hat, Inc.
4 # This library is free software; you can redistribute it and/or modify it under
5 # the terms of the GNU Lesser General Public License as published by the Free
6 # Software Foundation; either version 2.1 of the License, or (at your option)
9 # This library is distributed in the hope that it will be useful, but WITHOUT
10 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14 # You should have received a copy of the GNU General Public License along with
15 # this program. If not, see <http://www.gnu.org/licenses/>.
18 simplemediawiki is an extremely low-level wrapper to the MediaWiki API. It
19 automatically handles cookies and gzip compression so that you can make basic
20 calls to the API in the easiest way possible. It also provides a few functions
21 to make day-to-day API access easier.
23 To use this module, instantiate a MediaWiki object, passing it the URL of
24 api.php for the wiki you want to work with. Calls go through MediaWiki.call().
25 A generic login wrapper as well as functions to determine limits and get a list
26 of namespaces are provided for your convenience.
28 >>> from simplemediawiki import MediaWiki
29 >>> wiki = MediaWiki('http://en.wikipedia.org/w/api.php')
30 >>> wiki.call({'action': 'query', 'prop': 'revisions', 'titles': 'Main Page'})
31 {u'query': {u'pages': {...}}}
36 from iso8601 import iso8601
38 from StringIO import StringIO
45 Class to represent a MediaWiki installation with an enabled API.
47 api_url: URL to api.php (usually similar to http://example.com/w/api.php)
49 _cj = cookielib.CookieJar()
52 _psuedo_namespaces = None
54 def __init__(self, api_url):
55 self._api_url = api_url
57 def call(self, params):
59 Make a call to the wiki. Returns a dictionary that represents the JSON
62 params['format'] = 'json'
63 opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self._cj))
64 request = urllib2.Request(self._api_url, urllib.urlencode(params))
65 request.add_header('Accept-encoding', 'gzip')
66 response = opener.open(request)
67 if response.headers.get('Content-Encoding') == 'gzip':
68 compressed = StringIO(response.read())
69 gzipper = gzip.GzipFile(fileobj=compressed)
72 data = response.read()
73 return json.loads(data)
75 def login(self, user, passwd, token=None):
77 Convenience function for logging into the wiki. It should never be
78 necessary to provide a token argument; it is part of the login process
79 since MediaWiki 1.15.3 (see MediaWiki bug 23076).
81 data = {'action': 'login',
85 data['lgtoken'] = token
86 result = self.call(data)
87 if result['login']['result'] == 'Success':
89 elif result['login']['result'] == 'NeedToken' and not token:
90 return self.login(user, passwd, result['login']['token'])
94 def limits(self, low, high):
96 Convenience function for determining appropriate limits in the API. If
97 the logged in user has the "apihighlimits" right, it will return the
98 high argument; otherwise it will return the low argument.
100 if self._high_limits == None:
101 result = self.call({'action': 'query',
104 self._high_limits = 'apihighlimits' in \
105 result['query']['userinfo']['rights']
106 if self._high_limits:
111 def namespaces(self, psuedo=True):
113 Fetches a list of namespaces for this wiki.
115 if self._namespaces == None:
116 result = self.call({'action': 'query',
118 'siprop': 'namespaces'})
119 self._namespaces = {}
120 self._psuedo_namespaces = {}
121 for nsid in result['query']['namespaces']:
123 self._namespaces[int(nsid)] = \
124 result['query']['namespaces'][nsid]['*']
126 self._psuedo_namespaces[int(nsid)] = \
127 result['query']['namespaces'][nsid]['*']
130 retval.update(self._namespaces)
131 retval.update(self._psuedo_namespaces)
134 return self._namespaces
137 def parse_date(date):
139 Converts dates provided by the MediaWiki API into datetime.datetime
142 return iso8601.parse_date(date)
145 __author__ = 'Ian Weller <ian@ianweller.org>'