Added locking and moved work around / reduced repeat work at startup. Should clear up segfaults and improve startup time

This commit is contained in:
Anna 2010-05-04 11:03:32 -04:00
parent 7cce83c0f3
commit 6044fa27d2
3 changed files with 61 additions and 39 deletions

6
TODO
View File

@ -14,6 +14,6 @@ features:
bugs: bugs:
* Direct Messages have no names, only screen names (may not be fixable without * Direct Messages have no names, only screen names (may not be fixable without
considerable tweets to python-twitter) considerable tweaks to python-twitter)
* Can't always kill tabs * Can't always kill tabs - open tab list not always correctly populated?
* 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. * Can't always kill application

View File

@ -2,7 +2,19 @@
import re import re
import gtk import gtk
from threading import Thread from threading import Thread,RLock
from twitter import Api
class SafeApi(Api):
''' This is just a Twitter API with an RLock for multi-threaded access '''
def __init__(self, username, password):
Api.__init__(self, username, password)
self.lock = RLock()
# End class SafeApi
class GetTweets(Thread): class GetTweets(Thread):
def __init__(self, api, list_name, pane, num_entries, username): def __init__(self, api, list_name, pane, num_entries, username):
@ -15,6 +27,8 @@ class GetTweets(Thread):
def run(self): def run(self):
with self.api.lock:
# username/Home entries need to load the appropriate Home feed # username/Home entries need to load the appropriate Home feed
if self.list_name == self.username + '/Home': if self.list_name == self.username + '/Home':
statuses = self.api.GetHomeTimeline(count=self.num_entries) statuses = self.api.GetHomeTimeline(count=self.num_entries)
@ -64,6 +78,7 @@ class GetSingleTweet(Thread):
def run(self): def run(self):
statuses = [] statuses = []
with self.api.lock:
statuses.append(self.api.GetStatus(self.single_tweet)) statuses.append(self.api.GetStatus(self.single_tweet))
gtk.gdk.threads_enter() gtk.gdk.threads_enter()
@ -89,6 +104,7 @@ class GetFollowing(Thread):
screen_name = re.sub('user: ', '', self.user) screen_name = re.sub('user: ', '', self.user)
try: try:
with self.api.lock:
relationship = self.api.ShowFriendships(target_screen_name=screen_name) relationship = self.api.ShowFriendships(target_screen_name=screen_name)
following = relationship.source.following following = relationship.source.following
except HTTPError: except HTTPError:
@ -112,6 +128,7 @@ class GetVerified(Thread):
screen_name = re.sub('user: ', '', self.user) screen_name = re.sub('user: ', '', self.user)
try: try:
with self.api.lock:
user = self.api.GetUser(screen_name) user = self.api.GetUser(screen_name)
verified = user.verified verified = user.verified
except HTTPError: except HTTPError:

View File

@ -3,7 +3,6 @@
# Custom twitter client... mostly for learning Python # Custom twitter client... mostly for learning Python
import sys, ConfigParser, os, re, optparse, shelve import sys, ConfigParser, os, re, optparse, shelve
import twitter
import gtk, gtk.glade, gobject import gtk, gtk.glade, gobject
from urllib2 import HTTPError from urllib2 import HTTPError
from twitterwidgets import TweetPane from twitterwidgets import TweetPane
@ -47,7 +46,7 @@ class MyTwitter():
for item in config.sections(): for item in config.sections():
if (re.match(r'account', item)): if (re.match(r'account', item)):
username = config.get(item, 'username') username = config.get(item, 'username')
self.accounts[username] = twitter.Api(username=username, password=config.get(item, 'password')) self.accounts[username] = apithreads.SafeApi(username=username, password=config.get(item, 'password'))
self.username = self.accounts.keys()[0] self.username = self.accounts.keys()[0]
self.api = self.accounts[self.username] self.api = self.accounts[self.username]
@ -106,8 +105,9 @@ class MyTwitter():
# Add the tabs from last session to the notebook # Add the tabs from last session to the notebook
page_num = self.db['active_page'] page_num = self.db['active_page']
for tab, single_tweet in self.db['open_tabs']: for tab, single_tweet in self.db['open_tabs']:
self.add_to_notebook(tab, single_tweet) self.add_to_notebook(tab, single_tweet, update=False)
self.tweet_notebook.set_current_page(page_num) self.tweet_notebook.set_current_page(page_num)
self.update_windows()
# Put Home, @user, Direct Messages, and lists in the View menu for # Put Home, @user, Direct Messages, and lists in the View menu for
# each user # each user
@ -188,6 +188,7 @@ class MyTwitter():
def update_status(self): def update_status(self):
text = self.update_entry.get_text() text = self.update_entry.get_text()
self.update_entry.set_text("") self.update_entry.set_text("")
with self.api.lock:
self.api.PostUpdate(text, in_reply_to_status_id=self.reply_id) self.api.PostUpdate(text, in_reply_to_status_id=self.reply_id)
self.reply_id = None self.reply_id = None
self.update_status_bar('Tweet Posted') self.update_status_bar('Tweet Posted')
@ -224,6 +225,7 @@ class MyTwitter():
def on_retweet(self, widget, data): def on_retweet(self, widget, data):
with self.api.lock:
self.api.PostRetweet(data['id']) self.api.PostRetweet(data['id'])
@ -262,7 +264,7 @@ class MyTwitter():
self.remove_view(name, single_tweet) self.remove_view(name, single_tweet)
def add_to_notebook(self, name, single_tweet=None): def add_to_notebook(self, name, single_tweet=None, update=True):
# If it already exists, don't add it, just switch to it # If it already exists, don't add it, just switch to it
for i in range(self.tweet_notebook.get_n_pages()): for i in range(self.tweet_notebook.get_n_pages()):
pane = self.tweet_notebook.get_nth_page(i) pane = self.tweet_notebook.get_nth_page(i)
@ -308,6 +310,7 @@ class MyTwitter():
pane=new_pane, pane=new_pane,
single_tweet=single_tweet).start() single_tweet=single_tweet).start()
if update:
self.update_windows() self.update_windows()
self.tweet_notebook.set_current_page(-1) # switch to the new pane self.tweet_notebook.set_current_page(-1) # switch to the new pane
@ -356,9 +359,11 @@ class MyTwitter():
current_pane = self.tweet_notebook.get_nth_page(self.tweet_notebook.get_current_page()) current_pane = self.tweet_notebook.get_nth_page(self.tweet_notebook.get_current_page())
user_name = re.sub('^user: ', '', current_pane.get_list_name()) user_name = re.sub('^user: ', '', current_pane.get_list_name())
if current_pane.get_following(): if current_pane.get_following():
with self.api.lock:
self.api.DestroyFriendship(user_name) self.api.DestroyFriendship(user_name)
current_pane.set_following(False) current_pane.set_following(False)
else: else:
with self.api.lock:
self.api.CreateFriendship(user_name) self.api.CreateFriendship(user_name)
current_pane.set_following(True) current_pane.set_following(True)