Breaking the read into a seperate function make it look cleaner
[doneit] / src / rtm_api.py
index 0097e34..15c5d84 100644 (file)
@@ -9,7 +9,8 @@ import weakref
 import warnings
 import urllib
 import urllib2
-import md5
+import hashlib
+import time
 
 _use_simplejson = False
 try:
@@ -81,7 +82,7 @@ class RTMapi(object):
        def _sign(self, params):
                "Sign the parameters with MD5 hash"
                pairs = ''.join(['%s%s' % (k, v) for (k, v) in sortedItems(params)])
-               return md5.md5(self._secret+pairs).hexdigest()
+               return hashlib.md5(self._secret+pairs).hexdigest()
 
        @staticmethod
        def open_url(url, queryArgs=None):
@@ -90,6 +91,30 @@ class RTMapi(object):
                warnings.warn("Performing download of %s" % url, stacklevel=5)
                return urllib2.urlopen(url)
 
+       @staticmethod
+       def read(connection, timeout):
+               # It appears that urllib uses the non-blocking variant of file objects
+               # which means reads might not always be complete, so grabbing as much
+               # of the data as possible with a sleep in between to give it more time
+               # to grab data.
+               contentLengthField = "Content-Length"
+
+               chunks = []
+               chunk = connection.read()
+               while chunk:
+                       chunks.append(chunk)
+                       time.sleep(1)
+                       chunk = connection.read()
+               json = "".join(chunks)
+
+               if "Content-Length" in connection.info():
+                       assert len(json) == int(connection.info()["Content-Length"]), "The packet header promised %s of data but only was able to read %s of data" % (
+                               connection.info()["Content-Length"],
+                               len(json),
+                       )
+
+               return json
+
        def get(self, **params):
                "Get the XML response for the passed `params`."
                params['api_key'] = self._apiKey
@@ -97,7 +122,8 @@ class RTMapi(object):
                params['api_sig'] = self._sign(params)
 
                connection = self.open_url(SERVICE_URL, params)
-               json = connection.read()
+               json = self.read(connection, 5)
+
                data = DottedDict('ROOT', parse_json(json))
                rsp = data.rsp