diff --git a/TODO b/TODO index 97e938d..9c926ac 100644 --- a/TODO +++ b/TODO @@ -9,10 +9,11 @@ features: * Status bar icon * Support viewing a list of friends and unfollowing them * Support creating new lists and adding users to it (as well as removing users and deleting lists) - +* Need a new way to post failed tweet retrieval to the status bar bugs: * Direct Messages have no names, only screen names (may not be fixable without considerable tweets to python-twitter) * Can't always kill tabs +* New segfault at start that can't be reproduced with gdb. Must be a timing issue... adding locked access to some data in TweetPane didn't help... need locks to go with api objects. diff --git a/apithreads.py b/apithreads.py index 8ebc863..1b22523 100644 --- a/apithreads.py +++ b/apithreads.py @@ -54,6 +54,76 @@ class GetTweets(Thread): +class GetSingleTweet(Thread): + def __init__(self, api, pane, single_tweet): + Thread.__init__(self) + self.api = api + self.pane = pane + self.single_tweet = single_tweet + + + def run(self): + statuses = [] + statuses.append(self.api.GetStatus(self.single_tweet)) + + gtk.gdk.threads_enter() + try: + self.pane.update_window(statuses) + finally: + gtk.gdk.threads_leave() + + +### End class GetSingleTweet + + + +class GetFollowing(Thread): + def __init__(self, api, pane, user): + Thread.__init__(self) + self.api = api + self.pane = pane + self.user = user + + + def run(self): + screen_name = re.sub('user: ', '', self.user) + + try: + relationship = self.api.ShowFriendships(target_screen_name=screen_name) + following = relationship.source.following + except HTTPError: + following = false + + self.pane.set_following(following) + +### End class GetFollowing + + + +class GetVerified(Thread): + def __init__(self, api, pane, user): + Thread.__init__(self) + self.api = api + self.pane = pane + self.user = user + + + def run(self): + screen_name = re.sub('user: ', '', self.user) + + try: + user = self.api.GetUser(screen_name) + verified = user.verified + except HTTPError: + verified = false + + self.pane.set_verified(verified) + + +### End class GetVerified + + + # We use these classes to emulate a Status object when we need # one to be built out of something else. class Status(): diff --git a/mytwitter.py b/mytwitter.py index e9c55b6..3dbc989 100755 --- a/mytwitter.py +++ b/mytwitter.py @@ -288,9 +288,12 @@ class MyTwitter(): verified = False if re.match('user:', name): is_user = True - following = self.check_following(name) - verified = self.check_verified(name) - new_pane = TweetPane(name, num_entries=self.num_entries, single_tweet=single_tweet, is_user=is_user, following=following, verified=verified) + new_pane = TweetPane(name, num_entries=self.num_entries, single_tweet=single_tweet, is_user=is_user) + + if is_user: + apithreads.GetFollowing(api=self.api, pane=new_pane, user=name).start() + apithreads.GetVerified(api=self.api, pane=new_pane, user=name).start() + self.tweet_notebook.append_page_menu(new_pane, new_pane.get_tab_label(), gtk.Label(name)) self.tweet_notebook.set_tab_reorderable(new_pane, True) new_pane.get_tab_label().connect('close-clicked', self.remove_view_callback, name, single_tweet) @@ -301,14 +304,9 @@ class MyTwitter(): # Special logic for single tweet pane if single_tweet is not None: - try: - statuses = [] - statuses.append(self.api.GetStatus(single_tweet)) - new_pane.update_window(statuses) - except HTTPError: - self.tweet_notebook.remove_page(-1) - self.update_status_bar('Error retrieving tweet id: ' + str(single_tweet)) - return + apithreads.GetSingleTweet(api=self.api, + pane=new_pane, + single_tweet=single_tweet).start() self.update_windows() self.tweet_notebook.set_current_page(-1) # switch to the new pane @@ -359,34 +357,15 @@ class MyTwitter(): user_name = re.sub('^user: ', '', current_pane.get_list_name()) if current_pane.get_following(): self.api.DestroyFriendship(user_name) - current_pane.set_following(self.check_following(user_name)) + current_pane.set_following(False) else: self.api.CreateFriendship(user_name) - current_pane.set_following(self.check_following(user_name)) + current_pane.set_following(True) self.update_follow_button(current_pane) - # Name is the name of a pane, with the 'user: ' in place - def check_following(self, name): - screen_name = re.sub('user: ', '', name) - try: - relationship = self.api.ShowFriendships(target_screen_name=screen_name) - except HTTPError: - return False - return relationship.source.following - - - # Name is the name of a pane, with the 'user: ' in place - def check_verified(self, name): - screen_name = re.sub('user: ', '', name) - try: - user = self.api.GetUser(screen_name) - except HTTPError: - return False - return user.verified - - + # pane should be the currently active pane def update_follow_button(self, pane): if not pane.get_is_user(): self.following_button.set_label('') diff --git a/twitterwidgets.py b/twitterwidgets.py index b077254..9fc790d 100644 --- a/twitterwidgets.py +++ b/twitterwidgets.py @@ -1,6 +1,8 @@ import re import datetime, dateutil.tz import gtk, gobject +from threading import RLock + class TweetPane(gtk.ScrolledWindow): ''' @@ -13,9 +15,11 @@ class TweetPane(gtk.ScrolledWindow): It also gets some data from its parent, including num_entries ''' - def __init__(self, list_name, num_entries=20, single_tweet=None, is_user=False, following=False, verified=False): + def __init__(self, list_name, num_entries=20, single_tweet=None, is_user=False): gtk.ScrolledWindow.__init__(self) + self.data_lock = RLock() + self.updated_once = False self.list_name = list_name @@ -26,8 +30,8 @@ class TweetPane(gtk.ScrolledWindow): self.num_entries = 1 self.is_user = is_user - self.following = following - self.verified = verified + self.following = False + self.verified = False self.tab_label = CloseTabLabel(self.list_name) @@ -158,15 +162,25 @@ class TweetPane(gtk.ScrolledWindow): def get_following(self): - return self.following + with self.data_lock: + return self.following def get_verified(self): - return self.verified + with self.data_lock: + return self.verified def set_following(self, following): - self.following = following + print 'debug: set_following(): ' + str(following) + with self.data_lock: + self.following = following + + + def set_verified(self, verified): + print 'debug: set_verified(): ' + str(verified) + with self.data_lock: + self.verified = verified def get_is_user(self):