Move gallery merging logic to a helper class, to keep views as clean as possible.
[redakcja.git] / lib / wlapi / __init__.py
1 # -*- coding: utf-8 -*-
2 #
3 # This file is part of FNP-Redakcja, licensed under GNU Affero GPLv3 or later.
4 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
5 #
6 """
7    Abstraction over API for wolnelektury.pl
8 """
9 import urllib2
10 import functools
11 import django.utils.simplejson as json
12 import logging
13 logger = logging.getLogger("fnp.lib.wlapi")
14
15
16 class APICallException(Exception):
17
18     def __init__(self, cause=None):
19         super(Exception, self).__init__()
20         self.cause = cause
21
22     def __unicode__(self):
23         return u"%s, cause: %s" % (type(self).__name__, repr(self.cause))
24
25     def __str__(self):
26         return self.__unicode__().encode('utf-8')
27
28
29 def api_call(path, format="json"):
30     def wrapper(func):
31
32         @functools.wraps(func)
33         def wrapped(self, *args, **kwargs):
34             generator = func(self, *args, **kwargs)
35
36             data = generator.next()
37
38             # prepare request
39             rq = urllib2.Request(self.base_url + path + ".json")
40
41             # will send POST when there is data, GET otherwise
42             if data is not None:
43                 rq.add_data(json.dumps(data))
44                 rq.add_header("Content-Type", "application/json")
45
46             try:
47                 anwser = json.load(self.opener.open(rq))
48                 return generator.send(anwser)
49             except StopIteration:
50                 # by default, just return the anwser as a shorthand
51                 return anwser
52             except urllib2.HTTPError, error:
53                 return self._http_error(error)
54             except Exception, error:
55                 return self._error(error)
56         return wrapped
57
58     return wrapper
59
60
61 class WLAPI(object):
62
63     def __init__(self, **config_dict):
64         self.base_url = config_dict['URL']
65         self.auth_realm = config_dict['AUTH_REALM']
66         self.auth_user = config_dict['AUTH_USER']
67
68         digest_handler = urllib2.HTTPDigestAuthHandler()
69         digest_handler.add_password(
70                     realm=self.auth_realm, uri=self.base_url,
71                     user=self.auth_user, passwd=config_dict['AUTH_PASSWD'])
72
73         basic_handler = urllib2.HTTPBasicAuthHandler()
74         basic_handler.add_password(
75                     realm=self.auth_realm, uri=self.base_url,
76                     user=self.auth_user, passwd=config_dict['AUTH_PASSWD'])
77
78         self.opener = urllib2.build_opener(digest_handler, basic_handler)
79
80     def _http_error(self, error):
81         message = error.read()
82         logger.debug("HTTP ERROR: %s", message)
83         return self._error(message)
84
85     def _error(self, error):
86         raise APICallException(error)
87
88     @api_call("books")
89     def list_books(self):
90         yield
91
92     @api_call("books")
93     def publish_book(self, document):
94         yield {"text": document.text, "compressed": False}