]>
jfr.im git - z_archive/twitter.git/blob - twitter/api.py
3 from exceptions
import Exception
5 from twitter
.twitter_globals
import POST_ACTIONS
6 from twitter
.auth
import NoAuth
10 return sys
.hexversion
> 0x20600f0
15 import simplejson
as json
17 class TwitterError(Exception):
19 Base Exception thrown by the Twitter object when there is a
20 general error interacting with the API.
24 class TwitterHTTPError(TwitterError
):
26 Exception thrown by the Twitter object when there is an
27 HTTP error interacting with twitter.com.
29 def __init__(self
, e
, uri
, format
, uriparts
):
33 self
.uriparts
= uriparts
37 "Twitter sent status %i for URL: %s.%s using parameters: "
38 "(%s)\ndetails: %s" %(
39 self
.e
.code
, self
.uri
, self
.format
, self
.uriparts
,
42 class TwitterResponse(object):
44 Response from a twitter request. Behaves like a list or a string
45 (depending on requested format) but it has a few other interesting
48 `headers` gives you access to the response headers as an
49 httplib.HTTPHeaders instance. You can do
50 `response.headers.getheader('h')` to retrieve a header.
52 def __init__(self
, headers
):
53 self
.headers
= headers
56 def rate_limit_remaining(self
):
58 Remaining requests in the current rate-limit.
60 return int(self
.headers
.getheader('X-RateLimit-Remaining'))
63 def rate_limit_reset(self
):
65 Time in UTC epoch seconds when the rate limit will reset.
67 return int(self
.headers
.getheader('X-RateLimit-Reset'))
70 def wrap_response(response
, headers
):
71 response_typ
= type(response
)
72 class WrappedTwitterResponse(TwitterResponse
, response_typ
):
73 __doc__
= TwitterResponse
.__doc
__
75 def __init__(self
, response
, headers
):
76 response_typ
.__init
__(self
, response
)
77 TwitterResponse
.__init
__(self
, headers
)
79 return WrappedTwitterResponse(response
, headers
)
83 class TwitterCall(object):
85 self
, auth
, format
, domain
, uri
="", agent
=None,
86 uriparts
=None, secure
=True):
92 self
.uriparts
= uriparts
95 def __getattr__(self
, k
):
97 return object.__getattr
__(self
, k
)
98 except AttributeError:
100 auth
=self
.auth
, format
=self
.format
, domain
=self
.domain
,
101 agent
=self
.agent
, uriparts
=self
.uriparts
+ (k
,),
104 def __call__(self
, **kwargs
):
107 for uripart
in self
.uriparts
:
108 # If this part matches a keyword argument, use the
109 # supplied value otherwise, just use the part.
110 uriparts
.append(unicode(kwargs
.pop(uripart
, uripart
)))
111 uri
= u
'/'.join(uriparts
)
114 for action
in POST_ACTIONS
:
115 if uri
.endswith(action
):
119 # If an id kwarg is present and there is no id to fill in in
120 # the list of uriparts, assume the id goes at the end.
121 id = kwargs
.pop('id', None)
131 uriBase
= "http%s://%s/%s%s%s" %(
132 secure_str
, self
.domain
, uri
, dot
, self
.format
)
136 headers
.update(self
.auth
.generate_headers())
137 arg_data
= self
.auth
.encode_params(uriBase
, method
, kwargs
)
139 uriBase
+= '?' + arg_data
144 req
= urllib2
.Request(uriBase
, body
, headers
)
147 handle
= urllib2
.urlopen(req
)
148 if "json" == self
.format
:
149 res
= json
.loads(handle
.read())
150 return wrap_response(res
, handle
.headers
)
152 return wrap_response(handle
.read(), handle
.headers
)
153 except urllib2
.HTTPError
, e
:
157 raise TwitterHTTPError(e
, uri
, self
.format
, arg_data
)
159 class Twitter(TwitterCall
):
161 The minimalist yet fully featured Twitter API class.
163 Get RESTful data by accessing members of this class. The result
164 is decoded python objects (lists and dicts).
166 The Twitter API is documented here:
168 http://dev.twitter.com/doc
174 auth=OAuth(token, token_key, con_secret, con_secret_key)))
176 # Get the public timeline
177 twitter.statuses.public_timeline()
179 # Get a particular friend's timeline
180 twitter.statuses.friends_timeline(id="billybob")
182 # Also supported (but totally weird)
183 twitter.statuses.friends_timeline.billybob()
185 # Send a direct message
186 twitter.direct_messages.new(
188 text="I think yer swell!")
190 # Get the members of a particular list of a particular friend
191 twitter.user.listname.members(user="billybob", listname="billysbuds")
196 twitter_search = Twitter(domain="search.twitter.com")
198 # Find the latest search trends
199 twitter_search.trends()
201 # Search for the latest News on #gaza
202 twitter_search.search(q="#gaza")
205 Using the data returned
206 -----------------------
208 Twitter API calls return decoded JSON. This is converted into
209 a bunch of Python lists, dicts, ints, and strings. For example::
211 x = twitter.statuses.public_timeline()
213 # The first 'tweet' in the timeline
216 # The screen name of the user who wrote the first 'tweet'
217 x[0]['user']['screen_name']
223 If you prefer to get your Twitter data in XML format, pass
224 format="xml" to the Twitter object when you instantiate it::
226 twitter = Twitter(format="xml")
228 The output will not be parsed in any way. It will be a raw string
234 domain
="twitter.com", secure
=True, auth
=None,
237 Create a new twitter API connector.
239 Pass an `auth` parameter to use the credentials of a specific
240 user. Generally you'll want to pass an `OAuth`
243 twitter = Twitter(auth=OAuth(
244 token, token_secret, consumer_key, consumer_secret))
247 `domain` lets you change the domain you are connecting. By
248 default it's twitter.com but `search.twitter.com` may be
251 If `secure` is False you will connect with HTTP instead of
254 The value of `agent` is sent in the `X-Twitter-Client`
255 header. This is deprecated. Instead Twitter determines the
256 application using the OAuth Client Key and Client Key Secret
259 `api_version` is used to set the base uri. By default it's
260 nothing, but if you set it to '1' your URI will start with
266 if (format
not in ("json", "xml", "")):
267 raise ValueError("Unknown data format '%s'" %(format))
271 uriparts
+= (str(api_version
),)
273 TwitterCall
.__init
__(
274 self
, auth
=auth
, format
=format
, domain
=domain
,
275 secure
=secure
, uriparts
=uriparts
)
278 __all__
= ["Twitter", "TwitterError", "TwitterHTTPError", "TwitterResponse"]