kylewyg / pydelicious

Automatically exported from code.google.com/p/pydelicious
Other
0 stars 0 forks source link

Patch for more efficient authentication and a bit of error handling #4

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
By default pydelicious issues two http requests per API call. The first
call fails with the server sending back "401 Unauthorized", then urllib2
sends the request a second time with the authentication credentials. The
extra calls are inefficient. They also seem to trigger some rate limiting
in the delicious API servers that caused my program to break.

Below is a patch to just send all requests to Delicious with the
credentials in the Authorization: header even before Delicious gets around
to asking for it. I've verified this results in the first request working,
and my previously-throttled scripts are now working better.

As a bonus there's a second patch changing the error handling a bit.
Instead of returning 'False' on all errors, now it tries to return an error
string. pydelicious should be reworked to throw exceptions, but I'm too
lazy to do that now.

Index: pydelicious.py
===================================================================
--- pydelicious.py      (revision 2)
+++ pydelicious.py      (working copy)
@@ -51,7 +51,7 @@
 #  * rss parser muss auf viele möglichkeiten angepasst werden           

-import re, md5, httplib
+import re, md5, httplib, base64
 import urllib, urllib2, time
 # import datetime, 
 import StringIO
@@ -318,6 +318,11 @@
     request = urllib2.Request(DWS_API + url + params)
     if useUrlAsIs: request = urllib2.Request(url)
     request.add_header('User-Agent', USER_AGENT)
+
+    # Always send the authentication credentials; avoid an extra round
trip with 401
+    credentials = base64.encodestring("%s:%s" % (user, passwd))
+    request.add_header('Authorization', ('Basic %s' % credentials))
+
     if DEBUG: print "url:", request.get_full_url()
     try:
         o = urllib2.urlopen(request)            
@@ -340,7 +345,10 @@
         if (x.getroot().attrib.has_key("code") and
x.getroot().attrib["code"] == 'done') or x.getroot().text in ['done', 'ok']:
             l = True
         else :
-            l = False
+            if x.getroot().attrib.has_key("code"):
+                l = x.getroot().attrib["code"]
+            else:
+                l = False
     elif mode == 'update':
         l = x.getroot().attrib['time']
     elif mode == 'dates':

Original issue reported on code.google.com by nelson.m...@gmail.com on 15 Feb 2007 at 7:13

GoogleCodeExporter commented 9 years ago
Great work!  How do I apply this patch?

If it's easier I can give you SVN rights.  Let me know.

-Greg

Original comment by gregpin...@gmail.com on 15 Feb 2007 at 7:27

GoogleCodeExporter commented 9 years ago
You can manually apply my change via the 'patch' command line tool. Or if you 
give me
rights to SVN, I'll commit the changes myself. Before I do, two questions:

This changes the API; errors are no longer indicated by False, but rather 
something
other than True. I think in practice this is OK, do you?

8 of the tests fail when I run them with no username, the error is "HTTPError: 
HTTP
Error 401: Authorization Required". This fails in the trunk of SVN, not just my
modified copy. Do the tests pass for you?

Original comment by nelson.m...@gmail.com on 15 Feb 2007 at 9:06

GoogleCodeExporter commented 9 years ago
You should have SVN commit/edit rights now.  Please let me know.  

I'm ok with your changes.  If you'd prefer to have the methods raise Errors on
failure, I'm ok with that too.

I think the tests actually need to be updated.  They may not be reflecting the
current state of the code.  Feel free to update those, otherwise I wouldn't 
worry
about them too much for the time being.

Original comment by gregpin...@gmail.com on 15 Feb 2007 at 10:20

GoogleCodeExporter commented 9 years ago
I've submitted my change; it's in revision 3.

Original comment by nelson.m...@gmail.com on 15 Feb 2007 at 11:35