From f37246f30be3013e6c58233baa423de13cb175e8 Mon Sep 17 00:00:00 2001 From: Anna Date: Tue, 4 May 2010 14:32:43 -0400 Subject: [PATCH] Added error handling when API calls timeout --- apithreads.py | 57 ++++++++++++++++++++++++++--------------------- mytwitter.py | 31 ++++++++++++++++++++------ twitterwidgets.py | 10 +++++++++ 3 files changed, 66 insertions(+), 32 deletions(-) diff --git a/apithreads.py b/apithreads.py index baa1e95..bd1e4a0 100644 --- a/apithreads.py +++ b/apithreads.py @@ -4,6 +4,7 @@ import re import gtk from threading import Thread,RLock from twitter import Api +from urllib2 import HTTPError,URLError class SafeApi(Api): ''' This is just a Twitter API with an RLock for multi-threaded access ''' @@ -28,34 +29,37 @@ class GetTweets(Thread): def run(self): with self.api.lock: + try: + # username/Home entries need to load the appropriate Home feed + if self.list_name == self.username + '/Home': + statuses = self.api.GetHomeTimeline(count=self.num_entries) - # username/Home entries need to load the appropriate Home feed - if self.list_name == self.username + '/Home': - statuses = self.api.GetHomeTimeline(count=self.num_entries) + # For @username, check if it is one of our usernames, or + # just needs to be searched on + elif self.list_name == '@' + self.username: + statuses = self.api.GetMentions(count=self.num_entries) + elif re.match('@', self.list_name): + statuses = results_to_statuses(self.api.Search(self.list_name, rpp=self.num_entries)) - # For @username, check if it is one of our usernames, or - # just needs to be searched on - elif self.list_name == '@' + self.username: - statuses = self.api.GetMentions(count=self.num_entries) - elif re.match('@', self.list_name): - statuses = results_to_statuses(self.api.Search(self.list_name, rpp=self.num_entries)) + # Direct Messages should match like /Home, above + elif self.list_name == self.username + '/Direct Messages': + statuses = dms_to_statuses(self.api.GetDirectMessages()) - # Direct Messages should match like /Home, above - elif self.list_name == self.username + '/Direct Messages': - statuses = dms_to_statuses(self.api.GetDirectMessages()) + # User lookups go straight to the user + elif re.match(r'user: ', self.list_name): + statuses = self.api.GetUserTimeline(re.sub(r'^user: ', r'', self.list_name), count=self.num_entries) - # User lookups go straight to the user - elif re.match(r'user: ', self.list_name): - statuses = self.api.GetUserTimeline(re.sub(r'^user: ', r'', self.list_name), count=self.num_entries) + # Lists load the appropriate list from the appropriate account + elif re.match(r'list: ', self.list_name): + real_list = re.sub(r'list: .*/(.*)', r'\1', self.list_name) + statuses = self.api.GetListStatuses(real_list, per_page=self.num_entries) - # Lists load the appropriate list from the appropriate account - elif re.match(r'list: ', self.list_name): - real_list = re.sub(r'list: .*/(.*)', r'\1', self.list_name) - statuses = self.api.GetListStatuses(real_list, per_page=self.num_entries) + # Everything else is a straight search + else: + statuses = results_to_statuses(self.api.Search(self.list_name, rpp=self.num_entries)) - # Everything else is a straight search - else: - statuses = results_to_statuses(self.api.Search(self.list_name, rpp=self.num_entries)) + except HTTPError,URLError: + statuses = None gtk.gdk.threads_enter() try: @@ -79,7 +83,10 @@ class GetSingleTweet(Thread): def run(self): statuses = [] with self.api.lock: - statuses.append(self.api.GetStatus(self.single_tweet)) + try: + statuses.append(self.api.GetStatus(self.single_tweet)) + except HTTPError,URLError: + statuses = None gtk.gdk.threads_enter() try: @@ -107,7 +114,7 @@ class GetFollowing(Thread): with self.api.lock: relationship = self.api.ShowFriendships(target_screen_name=screen_name) following = relationship.source.following - except HTTPError: + except HTTPError,URLError: following = false self.pane.set_following(following) @@ -131,7 +138,7 @@ class GetVerified(Thread): with self.api.lock: user = self.api.GetUser(screen_name) verified = user.verified - except HTTPError: + except HTTPError,URLError: verified = false self.pane.set_verified(verified) diff --git a/mytwitter.py b/mytwitter.py index 6535411..9bde396 100755 --- a/mytwitter.py +++ b/mytwitter.py @@ -4,7 +4,7 @@ import sys, ConfigParser, os, re, optparse, shelve import gtk, gtk.glade, gobject -from urllib2 import HTTPError +from urllib2 import HTTPError,URLError from twitterwidgets import TweetPane import apithreads @@ -189,7 +189,13 @@ class MyTwitter(): text = self.update_entry.get_text() self.update_entry.set_text("") with self.api.lock: - self.api.PostUpdate(text, in_reply_to_status_id=self.reply_id) + try: + self.api.PostUpdate(text, in_reply_to_status_id=self.reply_id) + except HTTPError,URLError: + self.update_status_bar('Failed to post tweet') + self.reply_id = None + return + self.reply_id = None self.update_status_bar('Tweet Posted') @@ -226,7 +232,10 @@ class MyTwitter(): def on_retweet(self, widget, data): with self.api.lock: - self.api.PostRetweet(data['id']) + try: + self.api.PostRetweet(data['id']) + except HTTPError,URLError: + self.update_status_bar('Failed to retweet') def on_reply_to(self, widget, data): @@ -360,16 +369,24 @@ class MyTwitter(): user_name = re.sub('^user: ', '', current_pane.get_list_name()) if current_pane.get_following(): with self.api.lock: - self.api.DestroyFriendship(user_name) + try: + self.api.DestroyFriendship(user_name) + except HTTPError,URLError: + self.update_status_bar('Failed to unfollow user.') + return current_pane.set_following(False) else: with self.api.lock: - self.api.CreateFriendship(user_name) + try: + self.api.CreateFriendship(user_name) + except HTTPError,URLError: + self.update_status_bar('Failed to follow user.') + return current_pane.set_following(True) self.update_follow_button(current_pane) - - + + # pane should be the currently active pane def update_follow_button(self, pane): if not pane.get_is_user(): diff --git a/twitterwidgets.py b/twitterwidgets.py index 9fc790d..e9ebcf5 100644 --- a/twitterwidgets.py +++ b/twitterwidgets.py @@ -35,6 +35,8 @@ class TweetPane(gtk.ScrolledWindow): self.tab_label = CloseTabLabel(self.list_name) + self.error_message = gtk.Label('Failed to load tweet(s)') + # These handle determining which tweets are unread self.last_tweet_read = None self.latest_tweet = None @@ -52,6 +54,8 @@ class TweetPane(gtk.ScrolledWindow): viewport = gtk.Viewport() # Build us some labels... + tweet_box.pack_start(self.error_message) + for i in range(0, self.num_entries): self.tweets.append(TweetBox()) tweet_box.pack_start(self.tweets[i], expand=False) @@ -73,11 +77,17 @@ class TweetPane(gtk.ScrolledWindow): self.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS) self.show_all() + self.error_message.hide() for tweet in self.tweets: tweet.hide() def update_window(self, statuses): + if statuses is None: + self.error_message.show() + for i in range(0, self.num_entries): + self.tweets[i].hide() + if self.updated_once is False: self.updated_once = True