summaryrefslogtreecommitdiff
path: root/app/lib/flickr_api/method_call.py.bak
blob: a602e0136918e1ba5c5187d94730a18e01af8390 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
"""
    method_call module.

    This module is used to perform the calls to the REST interface.

    Author: Alexis Mignon (c)
    e-mail: alexis.mignon@gmail.com
    Date: 06/08/2011

"""
import urllib2
import urllib
import hashlib
import json

from .keys import *
from .flickrerrors import FlickrError, FlickrAPIError
from .cache import SimpleCache

REST_URL = "https://api.flickr.com/services/rest/"

CACHE = None


def enable_cache(cache_object=None):
    """ enable caching
    Parameters:
    -----------
    cache_object: object, optional
        A Django compliant cache object. If None (default), a SimpleCache
        object is used.
    """
    global CACHE
    CACHE = cache_object or SimpleCache()


def disable_cache():
    """Disable cachine capabilities
    """
    global CACHE
    CACHE = None


def send_request(url, data):
    """send a http request.
    """
    req = urllib2.Request(url, data)
    try:
        return urllib2.urlopen(req).read()
    except urllib2.HTTPError as e:
        raise FlickrError(e.read().split('&')[0])


def call_api(api_key=None, api_secret=None, auth_handler=None,
             needssigning=False, request_url=REST_URL, raw=False, **args):
    """
        Performs the calls to the Flickr REST interface.

    Parameters:
        api_key:
            The API_KEY to use. If none is given and a auth_handler is used
            the key stored in the auth_handler is used, otherwise, the values
            stored in the `flickr_keys` module are used.
        api_secret:
            The API_SECRET to use. If none is given and a auth_handler is used
            the key stored in the auth_handler is used, otherwise, the values
            stored in the `flickr_keys` module are used.
        auth_handler:
            The authentication handler object to use to perform authentication.
        request_url:
            The url to the rest interface to use by default the url in REST_URL
            is used.
        raw:
            if True the default xml response from the server is returned. If
            False (default) a dictionnary built from the JSON answer is
            returned.
        args:
            the arguments to pass to the method.
    """

    if not api_key:
        if auth_handler is not None:
            api_key = auth_handler.key
        else:
            api_key = keys.API_KEY
    if not api_secret:
        if auth_handler is not None:
            api_secret = auth_handler.secret
        else:
            api_secret = keys.API_SECRET

    if not api_key or not api_secret:
        raise FlickrError("The Flickr API keys have not been set")

    clean_args(args)
    args["api_key"] = api_key
    if not raw:
        args["format"] = 'json'
        args["nojsoncallback"] = 1

    if auth_handler is None:
        if needssigning:
            query_elements = args.items()
            query_elements.sort()
            sig = keys.API_SECRET + \
                  ["".join(["".join(e) for e in query_elements])]
            m = hashlib.md5()
            m.update(sig)
            api_sig = m.digest()
            args["api_sig"] = api_sig
        data = urllib.urlencode(args)
    else:
        data = auth_handler.complete_parameters(
             url=request_url, params=args
        ).to_postdata()

    if CACHE is None:
        resp = send_request(request_url, data)
    else:
        resp = CACHE.get(data) or send_request(request_url, data)
        if data not in CACHE:
            CACHE.set(data, resp)

    if raw:
        return resp

    try:
        resp = json.loads(resp)
    except ValueError as e:
        print(resp)
        raise e

    if resp["stat"] != "ok":
        raise FlickrAPIError(resp["code"], resp["message"])

    resp = clean_content(resp)

    return resp


def clean_content(d):
    """
    Cleans out recursively the keys comming from the JSON
    dictionnary.

    Namely: "_content" keys are replaces with their associated
        values if they are the only key of the dictionnary. Other
        wise they are replaces by a "text" key with the same value.
    """
    if isinstance(d, dict):
        d_clean = {}
        if len(d) == 1 and "_content" in d:
            return clean_content(d["_content"])
        for k, v in d.iteritems():
            if k == "_content":
                k = "text"
            d_clean[k] = clean_content(v)
        return d_clean
    elif isinstance(d, list):
        return [clean_content(i) for i in d]
    else:
        return d


def clean_args(args):
    """
        Reformat the arguments.
    """
    for k, v in args.items():
        if isinstance(v, bool):
            args[k] = int(v)