Made file locking more portable for FileCache.
authorJosh Roesslein <jroesslein@gmail.com>
Sun, 13 Sep 2009 20:01:22 +0000 (15:01 -0500)
committerJosh Roesslein <jroesslein@gmail.com>
Sun, 13 Sep 2009 20:01:22 +0000 (15:01 -0500)
CHANGES
ROADMAP
tests.py
tweepy/binder.py
tweepy/cache.py

diff --git a/CHANGES b/CHANGES
index 8fca1c07a1d2ad0a48fae46f318906f03c89f6b3..7e283f96e952354e318c4a490262bac0c281702d 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -23,5 +23,6 @@ during upgrade will be listed here.
       when user is not followed.
     + python 2.5 import syntax error fixed
     + python 2.5 timeout support for streaming API
+    + win32 failed import of fcntl in cache.py
 + Changed indents from 2 to 4 spaces
 
diff --git a/ROADMAP b/ROADMAP
index eccf70cfc65f03e685fd90a4fcd5ec827a6c805b..9d8a8da0c08b0dc27add4ac04715671fc94750a7 100644 (file)
--- a/ROADMAP
+++ b/ROADMAP
@@ -5,8 +5,7 @@ The plan of attack for the next version of Tweepy.
 + changing profile and background images [DONE]
 + finish search api [DONE]
 + autodetect authenticated user's ID [DONE]
-+ make oauth handler more web app friendly
-+ address file locking portability issues in file cache
++ address file locking portability issues in file cache [DONE]
 
 Future...
 =========
@@ -17,3 +16,5 @@ Future...
 + async requests
 + prepare for social graph changes mentioned on mailinglist
 + twitterfall reply API integration?
++ implement win32 file locking for FileCache
+
index 118944c96e21d81d766ebfb9627c068fcb810961..89fd8cbdad69f03aeaea8238f67945acff322c92 100644 (file)
--- a/tests.py
+++ b/tests.py
@@ -11,8 +11,8 @@ from tweepy import *
 
 """Configurations"""
 # Must supply twitter account credentials for tests
-username = 'tweebly'
-password = 'josh1987twitter'
+username = ''
+password = ''
 
 """Unit tests"""
 
index 3aa5e255279d2ef73af67553d87dcc3fb7713252..89626a89448bd995b7f5c10b901ca4d6fb0b7c18 100644 (file)
@@ -104,7 +104,11 @@ def bind_api(path, parser, allowed_param=None, method='GET', require_auth=False,
             raise TweepError(error_msg)
 
         # Pass returned body into parser and return parser output
-        out = parser(resp.read(), api)
+        try:
+            out = parser(resp.read(), api)
+        except Exception:
+            raise TweepError("Failed to parse returned data")
+
         conn.close()
 
         # validate result
index e1e9dce2307d7a0daf2f5fbdc1fbf4b1d776b61d..00d4b957f304447acf14d183d26bc5a7656e4d7f 100644 (file)
@@ -11,6 +11,13 @@ import hashlib
 import fcntl
 import cPickle as pickle
 
+try:
+    import fcntl
+except ImportError:
+    # Probably on a windows system
+    # TODO: use win32file
+    pass
+
 from . import memcache
 
 
@@ -127,12 +134,29 @@ class FileCache(Cache):
             self.lock = threading.Lock()
             FileCache.cache_locks[cache_dir] = self.lock
 
+        if os.name == 'posix':
+            self._lock_file = self._lock_file_posix
+            self._unlock_file = self._unlock_file_posix
+        elif os.name == 'nt':
+            self._lock_file = self._lock_file_win32
+            self._unlock_file = self._unlock_file_win32
+        else:
+            print 'Warning! FileCache locking not supported on this system!'
+            self._lock_file = self._lock_file_dummy
+            self._unlock_file = self._unlock_file_dummy
+
     def _get_path(self, key):
         md5 = hashlib.md5()
         md5.update(key)
         return os.path.join(self.cache_dir, md5.hexdigest())
 
-    def _lock_file(self, path, exclusive=True):
+    def _lock_file_dummy(self, path, exclusive=True):
+        return None
+
+    def _unlock_file_dummy(self, lock):
+        return
+
+    def _lock_file_posix(self, path, exclusive=True):
         lock_path = path + '.lock'
         if exclusive is True:
             f_lock = open(lock_path, 'w')
@@ -145,6 +169,17 @@ class FileCache(Cache):
             return None
         return f_lock
 
+    def _unlock_file_posix(self, lock):
+        lock.close()
+
+    def _lock_file_win32(self, path, exclusive=True):
+        # TODO: implement
+        return None
+
+    def _unlock_file_win32(self, lock):
+        # TODO: implement
+        return
+
     def _delete_file(self, path):
         os.remove(path)
         os.remove(path + '.lock')
@@ -161,7 +196,7 @@ class FileCache(Cache):
 
             # close and unlock file
             datafile.close()
-            f_lock.close()
+            self._unlock_file(f_lock)
 
     def get(self, key, timeout=None):
         return self._get(self._get_path(key), timeout)