__init__.py
4.99 KB
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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
import calendar
from datetime import datetime, timedelta
import hashlib
import json
import urllib
import urllib2
import floraconcierge
from floraconcierge import errors
from floraconcierge.client import handlers
from floraconcierge.client.types import from_dict
from floraconcierge.errors import get_result_error
class Environment(object):
def __init__(self):
self.language = 'en'
self.country = None
self.city = None
self.date = ApiClient.get_timestamp()
self.currency = 'usd'
self.ip = '127.0.0.1'
self.promo = None
self.user_auth_key = None
@property
def params(self):
return {
'_lang': self.language or '',
'_country': self.country or '',
'_city': self.city or '',
'_date': self.date or '',
'_currency': self.currency or '',
'_ip': self.ip,
'_promo': self.promo or '',
'_user_auth_key': self.user_auth_key or ''
}
class ApiResult(object):
def __init__(self, func, params=None, post=None):
self.func = func
self.params = params
self.post = post
self.url = None
self.body = None
self.http_code = None
self.time = None
self.size = None
self._data = None
def process(self, response):
try:
self._data = json.loads(response, object_hook=from_dict)
self.size = len(response)
except ValueError, e:
self.body = response
raise errors.MalformedJSONResultError(self, e.message)
if self._data.error.code:
raise get_result_error(self, self._data.error)
@property
def value(self):
return self._data.result
def dump(self):
return self.value
class ApiClient(object):
def __init__(self, api_id, secret_key):
self._api_id = api_id
self._secret_key = secret_key
self.env = Environment()
self._opener = urllib2.build_opener(
handlers.UserAgentProcessor(floraconcierge.HTTP_CLIENT_UA),
handlers.GZipProcessor()
)
self._api_endpoint = 'http://api.floraconcierge.com/v1/'
self._debug = False
self._calls = list()
self._calls_time = timedelta()
# importing here avoid import recursion
from floraconcierge.services import Manager
self.services = Manager(self)
@property
def api_endpoint(self):
return self._api_endpoint
@api_endpoint.setter
def api_endpoint(self, url):
self._api_endpoint = url
@property
def debug(self):
return self._debug
@debug.setter
def debug(self, value):
self._debug = bool(value)
@staticmethod
def get_timestamp(time=None):
time = time or datetime.now()
return calendar.timegm(time.timetuple())
@property
def calls(self):
return self._calls
@calls.deleter
def calls(self):
self._calls = list()
self._calls_time = timedelta()
def sign(self, **kwargs):
sign = dict((k, v) for k, v in kwargs.iteritems() if k[0] != '_')
keys = sign.keys()
keys.sort()
tosign = []
for k in keys:
tosign.append("%s=%s" % (k, sign[k]))
tosign = "".join(tosign)
return hashlib.sha1("%s:%s" % (self._secret_key, tosign)).hexdigest()
def call(self, func, get=None, post=None):
get, post, start = get or dict(), post or dict(), datetime.now()
assert isinstance(func, (str, unicode)), 'Supported only string function name'
assert isinstance(get, dict), 'Supported only dict GET data'
assert isinstance(post, dict), 'Supported only dict POST data'
_get, _post = get.copy(), post.copy()
get.update({
'_sign': self.sign(**get),
'_api_id': self._api_id,
})
get.update(self.env.params)
get = dict((k, v) for k, v in get.iteritems() if k[0] != '_' or v)
url = "%s%s?%s" % (self._api_endpoint, func.lstrip(), urllib.urlencode(get))
request = urllib2.Request(url)
if _post:
request.data = json.dumps(_post)
try:
response = self._opener.open(request)
body = response.read()
except urllib2.URLError, e:
raise errors.HTTPError(e, e.reason)
result = ApiResult(func, _get, _post)
result.url = response.geturl()
result.http_code = response.getcode()
result.time = datetime.now() - start
if self.debug:
result.body = body
self._calls.append(result)
self._calls_time += result.time
result.process(body)
return result.value
def callstats(self):
return (self._calls_time, self._calls)
class Service(object):
"""
@type client: ApiClient
"""
def __init__(self, client):
self._client = client
def _callapi(self, func, get=None, post=None):
return self._client.call(func, get, post)