# -*- coding: utf-8  -*-
"""
Interface functions to Mediawiki's api.php
"""
#
# (C) Pywikipedia bot team, 2007
#
# Distributed under the terms of the MIT license.
#
__version__ = '$Id: $'


import urllib
import http


class API:

    def __init__(self, site):
        self.site = site

    def query(prop, **kwargs):
        params = dict(kwargs)
        params['action'] = 'query'
        if not params.has_key('format'): #Most probably, we want the JSON format
            params['format'] = 'json'

        return http.HTTP(None).POST('/w/api.php',params) #TODO: Use site's HTTP object instead

@@ -213,21 +213,128 @@
 ttp%0A
-%0A%0Aclass API:%0A
+import simplejson as json%0Aimport warnings%0A%0Aclass APIError(Exception):%0A    %22%22%22The wiki site returned an error message.%22%22%22
 %0A   
@@ -357,136 +357,278 @@
 lf, 
-site
+errordict
 ):%0A   
+  
+   %22%22%22Save error dict returned by MW API.%22%22%22%0A
      
+   
 self.
-site = site%0A%0A    def query(prop, **kwargs):%0A        params = dict(kwargs)%0A        params%5B'action'%5D = 'query'
+errors = errordict%0A%0A    def __str__(self):%0A        return %22%25(code)s: %25(info)s%22 %25 self.errors%0A%0A%0Aclass API:%0A%0A    def __init__(self, site):%0A        self.site = site%0A%0A    def request(self, **params):
 %0A   
@@ -743,17 +743,16 @@
  'json'%0A
-%0A
         
@@ -838,8 +838,2249 @@
 instead%0A
+%0A    def query(self, **params):%0A        if not params.has_key('action'):%0A            params%5B'action'%5D = 'query'%0A        return self.request(**params)%0A%0A    def query_response(self, **params):%0A        %22%22%22Submit a query and parse the response, returning a dict or None.%22%22%22%0A        if params.has_key('format') and params%5B'format'%5D != 'json':%0A            raise TypeError(%22Query format '%25s' cannot be parsed.%22 %25 params%5B'format'%5D)%0A        while True:%0A            httpcode, rawdata = self.query(**params)%0A            if httpcode != 200:%0A                raise APIError(%0A                    %7B'code': httpcode,%0A                     'info': %22HTTP error code received.%22,%0A                     'data': rawdata%7D)%0A            if rawdata.startswith(u%22unknown_action%22):%0A                e = %7B'code': data%5B:14%5D, 'info': data%5B16:%5D%7D%0A                raise APIError(e)%0A            try:%0A                result = json.loads(rawdata)%0A            except ValueError:%0A                # if the result isn't valid JSON, there must be a server%0A                # problem.  Wait a few seconds and try again%0A                # TODO: implement a throttle%0A                warnings.warn(%0A%22Non-JSON response received from server %25s; the server may be down.%22%0A                              %25 self.site)%0A                continue%0A            if type(result) is dict:%0A                if result.has_key(%22error%22):%0A                    # raise error%0A                    raise APIError(result%5B'error'%5D)%0A                if result.has_key(%22query%22):%0A                    return result%0A                raise APIError(%0A                    %7B'code': %22Unknown API error%22,%0A                     'info': %22Response received with no 'query' key.%22,%0A                     'data': result%7D)%0A            if type(result) is list:%0A                if result == %5B%5D:%0A                    return None%0A                raise APIError(%0A                    %7B'code': %22Unknown API error%22,%0A                     'info': %22Query returned a list instead of a dict.%22,%0A                     'data': result%7D)%0A            raise APIError(%0A                %7B'code': %22Unknown API error%22,%0A                 'info': %22Unable to process query response of type %25s.%22%0A                         %25 type(result),%0A                 'data': result%7D)%0A    %0A

Generalize query method; add some response processing and error handling.