]>
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 # Multiple inheritance makes my inner Java nerd cry. Why can't I just
71 # add arbitrary attributes to list or str objects?! Guido, we need to
73 class TwitterJsonResponse(TwitterResponse
, list):
74 __doc__
= """Twitter JSON Response
75 """ + TwitterResponse
.__doc
__
76 def __init__(self
, lst
, headers
):
77 TwitterResponse
.__init
__(self
, headers
)
78 list.__init
__(self
, lst
)
80 class TwitterXmlResponse(TwitterResponse
, str):
81 __doc__
= """Twitter XML Response
82 """ + TwitterResponse
.__doc
__
85 class TwitterCall(object):
87 self
, auth
, format
, domain
, uri
="", agent
=None,
88 uriparts
=None, secure
=True):
94 self
.uriparts
= uriparts
97 def __getattr__(self
, k
):
99 return object.__getattr
__(self
, k
)
100 except AttributeError:
102 auth
=self
.auth
, format
=self
.format
, domain
=self
.domain
,
103 agent
=self
.agent
, uriparts
=self
.uriparts
+ (k
,),
106 def __call__(self
, **kwargs
):
109 for uripart
in self
.uriparts
:
110 # If this part matches a keyword argument, use the
111 # supplied value otherwise, just use the part.
112 uriparts
.append(unicode(kwargs
.pop(uripart
, uripart
)))
113 uri
= u
'/'.join(uriparts
)
116 for action
in POST_ACTIONS
:
117 if uri
.endswith(action
):
121 # If an id kwarg is present and there is no id to fill in in
122 # the list of uriparts, assume the id goes at the end.
123 id = kwargs
.pop('id', None)
133 uriBase
= "http%s://%s/%s%s%s" %(
134 secure_str
, self
.domain
, uri
, dot
, self
.format
)
138 headers
.update(self
.auth
.generate_headers())
139 arg_data
= self
.auth
.encode_params(uriBase
, method
, kwargs
)
141 uriBase
+= '?' + arg_data
146 req
= urllib2
.Request(uriBase
, body
, headers
)
149 handle
= urllib2
.urlopen(req
)
150 if "json" == self
.format
:
151 return TwitterJsonResponse(json
.loads(handle
.read()),
154 r
= TwitterXmlResponse(handle
.read())
155 r
.headers
= handle
.headers
157 except urllib2
.HTTPError
, e
:
161 raise TwitterHTTPError(e
, uri
, self
.format
, arg_data
)
163 class Twitter(TwitterCall
):
165 The minimalist yet fully featured Twitter API class.
167 Get RESTful data by accessing members of this class. The result
168 is decoded python objects (lists and dicts).
170 The Twitter API is documented here:
172 http://dev.twitter.com/doc
178 auth=OAuth(token, token_key, con_secret, con_secret_key)))
180 # Get the public timeline
181 twitter.statuses.public_timeline()
183 # Get a particular friend's timeline
184 twitter.statuses.friends_timeline(id="billybob")
186 # Also supported (but totally weird)
187 twitter.statuses.friends_timeline.billybob()
189 # Send a direct message
190 twitter.direct_messages.new(
192 text="I think yer swell!")
194 # Get the members of a particular list of a particular friend
195 twitter.user.listname.members(user="billybob", listname="billysbuds")
200 twitter_search = Twitter(domain="search.twitter.com")
202 # Find the latest search trends
203 twitter_search.trends()
205 # Search for the latest News on #gaza
206 twitter_search.search(q="#gaza")
209 Using the data returned
210 -----------------------
212 Twitter API calls return decoded JSON. This is converted into
213 a bunch of Python lists, dicts, ints, and strings. For example::
215 x = twitter.statuses.public_timeline()
217 # The first 'tweet' in the timeline
220 # The screen name of the user who wrote the first 'tweet'
221 x[0]['user']['screen_name']
227 If you prefer to get your Twitter data in XML format, pass
228 format="xml" to the Twitter object when you instantiate it::
230 twitter = Twitter(format="xml")
232 The output will not be parsed in any way. It will be a raw string
238 domain
="twitter.com", secure
=True, auth
=None,
241 Create a new twitter API connector.
243 Pass an `auth` parameter to use the credentials of a specific
244 user. Generally you'll want to pass an `OAuth`
247 twitter = Twitter(auth=OAuth(
248 token, token_secret, consumer_key, consumer_secret))
251 `domain` lets you change the domain you are connecting. By
252 default it's twitter.com but `search.twitter.com` may be
255 If `secure` is False you will connect with HTTP instead of
258 The value of `agent` is sent in the `X-Twitter-Client`
259 header. This is deprecated. Instead Twitter determines the
260 application using the OAuth Client Key and Client Key Secret
263 `api_version` is used to set the base uri. By default it's
264 nothing, but if you set it to '1' your URI will start with
270 if (format
not in ("json", "xml", "")):
271 raise ValueError("Unknown data format '%s'" %(format))
275 uriparts
+= (str(api_version
),)
277 TwitterCall
.__init
__(
278 self
, auth
=auth
, format
=format
, domain
=domain
,
279 secure
=secure
, uriparts
=uriparts
)
282 __all__
= ["Twitter", "TwitterError", "TwitterHTTPError", "TwitterJsonResponse",
283 "TwitterXmlResponse"]