]> jfr.im git - z_archive/twitter.git/blobdiff - twitter/api.py
Merge commit 'origin/cmdline_search' into cmdline_search_merge
[z_archive/twitter.git] / twitter / api.py
index 47dae5d3f19941340244b55f66e45fa463feeb33..42ec7274c5d9da5b25950c4a79f5d13d28b38412 100644 (file)
@@ -2,10 +2,12 @@
 from base64 import b64encode
 from urllib import urlencode
 
 from base64 import b64encode
 from urllib import urlencode
 
-import httplib
+import urllib2
 
 from exceptions import Exception
 
 
 from exceptions import Exception
 
+from twitter.twitter_globals import POST_ACTIONS
+
 def _py26OrGreater():
     import sys
     return sys.hexversion > 0x20600f0
 def _py26OrGreater():
     import sys
     return sys.hexversion > 0x20600f0
@@ -22,45 +24,48 @@ class TwitterError(Exception):
     """
     pass
 
     """
     pass
 
-# These actions require POST http requests instead of GET
-_POST_ACTIONS = [
-    "create", "update", "destroy", "new", "follow", "leave",
-    ]
-
 class TwitterCall(object):
     def __init__(
 class TwitterCall(object):
     def __init__(
-        self, username, password, format, domain, uri="", agent=None):
+        self, username, password, format, domain, uri="", agent=None, encoded_args=None):
         self.username = username
         self.password = password
         self.format = format
         self.domain = domain
         self.uri = uri
         self.agent = agent
         self.username = username
         self.password = password
         self.format = format
         self.domain = domain
         self.uri = uri
         self.agent = agent
+        self.encoded_args = encoded_args
+
     def __getattr__(self, k):
         try:
             return object.__getattr__(self, k)
         except AttributeError:
             return TwitterCall(
                 self.username, self.password, self.format, self.domain,
     def __getattr__(self, k):
         try:
             return object.__getattr__(self, k)
         except AttributeError:
             return TwitterCall(
                 self.username, self.password, self.format, self.domain,
-                self.uri + "/" + k, self.agent)
+                self.uri + "/" + k, self.agent, self.encoded_args)
+
     def __call__(self, **kwargs):
         uri = self.uri
         method = "GET"
     def __call__(self, **kwargs):
         uri = self.uri
         method = "GET"
-        for action in _POST_ACTIONS:
+        for action in POST_ACTIONS:
             if self.uri.endswith(action):
                 method = "POST"
                 if (self.agent):
                     kwargs["source"] = self.agent
                 break
             if self.uri.endswith(action):
                 method = "POST"
                 if (self.agent):
                     kwargs["source"] = self.agent
                 break
-        
-        id = kwargs.pop('id', None)
-        if id:
-            uri += "/%s" %(id)
-            
-        encoded_kwargs = urlencode(kwargs.items())
+
+        if (not self.encoded_args):
+            if kwargs.has_key('id'):
+                uri += "/%s" %(kwargs['id'])
+    
+            self.encoded_args = urlencode(kwargs.items())
+
         argStr = ""
         argStr = ""
-        if kwargs and (method == "GET"):
-            argStr = "?" + encoded_kwargs
+        argData = None
+        if (method == "GET"):
+            if self.encoded_args:
+                argStr = "?%s" %(self.encoded_args)
+        else:
+            argData = self.encoded_args
 
         headers = {}
         if (self.agent):
 
         headers = {}
         if (self.agent):
@@ -68,38 +73,29 @@ class TwitterCall(object):
         if (self.username):
             headers["Authorization"] = "Basic " + b64encode("%s:%s" %(
                 self.username, self.password))
         if (self.username):
             headers["Authorization"] = "Basic " + b64encode("%s:%s" %(
                 self.username, self.password))
-        if method == "POST":
-            headers["Content-type"] = "application/x-www-form-urlencoded"
-            headers["Content-length"] = len(encoded_kwargs)
-        
-        c = httplib.HTTPConnection(self.domain)
+
+        req = urllib2.Request(
+                "http://%s/%s.%s%s" %(self.domain, uri, self.format, argStr),
+                argData, headers
+            )
         try:
         try:
-            c.putrequest(method, "%s.%s%s" %(
-                uri, self.format, argStr))
-            for item in headers.iteritems():
-                c.putheader(*item)
-            c.endheaders()
-            if method == "POST":
-                c.send(encoded_kwargs)
-            r = c.getresponse()
-
-            if (r.status == 304):
+            handle = urllib2.urlopen(req)
+            if "json" == self.format:
+                return json.loads(handle.read())
+            else:
+                return handle.read()
+        except urllib2.HTTPError, e:
+            if (e.code == 304):
                 return []
                 return []
-            elif (r.status != 200):
+            else:
                 raise TwitterError(
                     "Twitter sent status %i for URL: %s.%s using parameters: (%s)\ndetails: %s" %(
                 raise TwitterError(
                     "Twitter sent status %i for URL: %s.%s using parameters: (%s)\ndetails: %s" %(
-                        r.status, uri, self.format, encoded_kwargs, r.read()))
-            if "json" == self.format:
-                return json.loads(r.read())
-            else:
-                return r.read()
-        finally:
-            c.close()
+                        e.code, uri, self.format, encoded_kwargs, e.fp.read()))
 
 class Twitter(TwitterCall):
     """
     The minimalist yet fully featured Twitter API class.
 
 class Twitter(TwitterCall):
     """
     The minimalist yet fully featured Twitter API class.
-    
+
     Get RESTful data by accessing members of this class. The result
     is decoded python objects (lists and dicts).
 
     Get RESTful data by accessing members of this class. The result
     is decoded python objects (lists and dicts).
 
@@ -107,27 +103,27 @@ class Twitter(TwitterCall):
 
       http://apiwiki.twitter.com/
       http://groups.google.com/group/twitter-development-talk/web/api-documentation
 
       http://apiwiki.twitter.com/
       http://groups.google.com/group/twitter-development-talk/web/api-documentation
-    
+
     Examples::
     Examples::
-    
+
       twitter = Twitter("hello@foo.com", "password123")
       twitter = Twitter("hello@foo.com", "password123")
-      
+
       # Get the public timeline
       twitter.statuses.public_timeline()
       # Get the public timeline
       twitter.statuses.public_timeline()
-      
+
       # Get a particular friend's timeline
       twitter.statuses.friends_timeline(id="billybob")
       # Get a particular friend's timeline
       twitter.statuses.friends_timeline(id="billybob")
-      
+
       # Also supported (but totally weird)
       twitter.statuses.friends_timeline.billybob()
       # Also supported (but totally weird)
       twitter.statuses.friends_timeline.billybob()
-      
+
       # Send a direct message
       twitter.direct_messages.new(
           user="billybob",
           text="I think yer swell!")
 
     Searching Twitter::
       # Send a direct message
       twitter.direct_messages.new(
           user="billybob",
           text="I think yer swell!")
 
     Searching Twitter::
-        
+
       twitter_search = Twitter(domain="search.twitter.com")
 
       # Find the latest search trends
       twitter_search = Twitter(domain="search.twitter.com")
 
       # Find the latest search trends
@@ -148,14 +144,14 @@ class Twitter(TwitterCall):
 
       # The screen name of the user who wrote the first 'tweet'
       x[0]['user']['screen_name']
 
       # The screen name of the user who wrote the first 'tweet'
       x[0]['user']['screen_name']
-    
+
     Getting raw XML data::
     Getting raw XML data::
-    
+
       If you prefer to get your Twitter data in XML format, pass
       format="xml" to the Twitter object when you instantiate it:
       If you prefer to get your Twitter data in XML format, pass
       format="xml" to the Twitter object when you instantiate it:
-      
+
       twitter = Twitter(format="xml")
       twitter = Twitter(format="xml")
-      
+
       The output will not be parsed in any way. It will be a raw string
       of XML.
     """
       The output will not be parsed in any way. It will be a raw string
       of XML.
     """