6
6
import urllib
7
7
import urllib2
8
8
9
- __version__ = '0.4.9 '
9
+ __version__ = '0.5.0 '
10
10
__author__ = 'Liang Cha (ckmx945@gmail.com)'
11
11
12
12
25
25
26
26
_CONTENT_TYPE_MEDIA = ('image/jpeg' , 'audio/amr' , 'video/mpeg4' )
27
27
28
+ _MEIDA_TYPE = ('mpeg4' , 'jpeg' , 'jpg' , 'gif' , 'png' , 'bmp' , 'mp3' , 'wav' , 'wma' , 'amr' )
29
+
28
30
_CONTENT_TYPE_JSON = (
29
31
'application/json; encoding=utf-8' ,
30
32
'application/json' ,
@@ -49,6 +51,7 @@ class APIError(StandardError):
49
51
'''
50
52
raise APIError if reciving json message indicating failure.
51
53
'''
54
+
52
55
def __init__ (self , error_code , error_msg ):
53
56
self .error_code = error_code
54
57
self .error_msg = error_msg
@@ -62,6 +65,7 @@ class AccessTokenError(APIError):
62
65
'''
63
66
raise AccessTokenError if reciving json message indicating failure.
64
67
'''
68
+
65
69
def __init__ (self , error_code , error_msg ):
66
70
APIError .__init__ (self , error_code , error_msg )
67
71
@@ -73,6 +77,7 @@ class JsonDict(dict):
73
77
'''
74
78
general json object that allows attributes to bound to and also behaves like a dict
75
79
'''
80
+
76
81
def __getattr__ (self , attr ):
77
82
try :
78
83
return self [attr ]
@@ -84,7 +89,7 @@ def __setattr__(self, attr, value):
84
89
85
90
86
91
def _parse_json (s ):
87
- ' parse str into JsonDict '
92
+ ''' parse str into JsonDict '' '
88
93
89
94
def _obj_hook (pairs ):
90
95
o = JsonDict ()
@@ -108,13 +113,13 @@ def _encode_params(**kw):
108
113
if k == 'body' :
109
114
body = v
110
115
continue
111
- if k in [ 'pic' ] :
116
+ if k in _MEIDA_TYPE :
112
117
continue
113
118
if isinstance (v , basestring ):
114
119
qv = v .encode ('utf-8' ) if isinstance (v , unicode ) else v
115
120
args .append ('%s=%s' % (k , urllib .quote (qv )))
116
121
else :
117
- if v == None :
122
+ if v is None :
118
123
args .append ('%s=' % (k ))
119
124
else :
120
125
qv = str (v )
@@ -126,25 +131,23 @@ def _encode_multipart(**kw):
126
131
'''
127
132
build a multipart/form-data body with randomly generated boundary
128
133
'''
129
- boundary = '----------%s' % hex (int (time .time ()) * 1000 )
130
134
data = []
131
- for k , v in kw .iteritems ():
132
- if hasattr (v , 'read' ):
133
- data .append ('--%s' % boundary )
134
- filename = getattr (v , 'name' , '' )
135
- if filename == None or len (filename ) == 0 :
136
- filename = '/tmp/test.jpg'
137
- content = v .read ()
138
- data .append ('Content-Disposition: form-data; name="%s"; filename="%s"' % (k , filename ))
139
- data .append ('Content-Length: %d' % len (content ))
140
- #data.append('Content-Type: application/octet-stream')
141
- data .append ('Content-Type: image/jpeg' )
142
- data .append ('Content-Transfer-Encoding: binary\r \n ' )
143
- data .append (content )
144
- if hasattr (v , 'close' ):
145
- v .close ()
146
- break
135
+ boundary = '----------%s' % hex (int (time .time ()) * 1000 )
136
+ media_key = [key for key in _MEIDA_TYPE if key in kw .keys ()]
137
+ media_key = media_key [0 ] if media_key else 'null'
138
+ fd = kw .get (media_key )
139
+ media_type = kw .get ('type' ) if kw .has_key ('type' ) else 'null'
140
+ content = fd .read () if hasattr (fd , 'read' ) else 'null'
141
+ filename = getattr (fd , 'name' , None )
142
+ if filename is None : filename = '/tmp/fake.%s' % (media_key )
143
+ data .append ('--%s' % boundary )
144
+ data .append ('Content-Disposition: form-data; name="%s"; filename="%s"' % (media_key , filename ))
145
+ data .append ('Content-Length: %d' % len (content ))
146
+ data .append ('Content-Type: %s/%s' % (media_type , media_key ))
147
+ data .append ('Content-Transfer-Encoding: binary\r \n ' )
148
+ data .append (content )
147
149
data .append ('--%s--\r \n ' % boundary )
150
+ if hasattr (fd , 'close' ): fd .close ()
148
151
return '\r \n ' .join (data ), boundary
149
152
150
153
@@ -196,9 +199,9 @@ def _http_call(the_url, method, token, **kw):
196
199
'''
197
200
send an http request and return a json object if no error occurred.
198
201
'''
202
+ body = None
199
203
params = None
200
204
boundary = None
201
- body = None
202
205
(params , body ) = _encode_params (** kw )
203
206
if method == _HTTP_FILE :
204
207
the_url = the_url .replace ('https://api.' , 'http://file.api.' )
@@ -210,8 +213,7 @@ def _http_call(the_url, method, token, **kw):
210
213
http_url = '%s&%s' % (the_url , params ) if (method == _HTTP_GET or method == _HTTP_FILE ) else the_url
211
214
http_body = str (body ) if (method == _HTTP_POST ) else body
212
215
req = urllib2 .Request (http_url , data = http_body )
213
- if boundary != None :
214
- req .add_header ('Content-Type' , 'multipart/form-data; boundary=%s' % boundary )
216
+ if boundary : req .add_header ('Content-Type' , 'multipart/form-data; boundary=%s' % boundary )
215
217
try :
216
218
resp = urllib2 .urlopen (req , timeout = 8 )
217
219
except urllib2 .HTTPError , e :
@@ -319,9 +321,15 @@ def refurbish_access_token(self):
319
321
self .del_access_token ()
320
322
self .request_access_token ()
321
323
322
- def set_access_token (self , token , expires ):
324
+ def set_access_token (self , token , expires_in , persistence = False ):
323
325
self .access_token = token
324
- self .expires = expires
326
+ self .expires = expires_in + int (time .time ())
327
+ if persistence :
328
+ token_key = 'access_token_%s' % (self .app_id )
329
+ expires_key = 'expires_%s' % (self .app_id )
330
+ self .mc .set (token_key , token , time = expires_in )
331
+ self .mc .set (expires_key , self .expires , time = expires_in )
332
+ if self .fc : self .mc .save ()
325
333
326
334
def is_expires (self ):
327
335
return not self .access_token or int (time .time ()) >= (self .expires - 10 )
@@ -360,7 +368,7 @@ def __init__(self, client, name):
360
368
self ._name = name
361
369
362
370
def __getattr__ (self , attr ):
363
- if attr == ' _get' :
371
+ if attr in ( 'dget' , ' _get') :
364
372
return _Executable (self ._client , _HTTP_GET , self ._name )
365
373
if attr == 'post' :
366
374
return _Executable (self ._client , _HTTP_POST , self ._name )
0 commit comments