Added locking and moved work around / reduced repeat work at startup. Should clear up segfaults and improve startup time
This commit is contained in:
parent
7cce83c0f3
commit
6044fa27d2
6
TODO
6
TODO
|
@ -14,6 +14,6 @@ features:
|
|||
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.
|
||||
considerable tweaks to python-twitter)
|
||||
* Can't always kill tabs - open tab list not always correctly populated?
|
||||
* Can't always kill application
|
||||
|
|
|
@ -2,7 +2,19 @@
|
|||
|
||||
import re
|
||||
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):
|
||||
def __init__(self, api, list_name, pane, num_entries, username):
|
||||
|
@ -15,33 +27,35 @@ class GetTweets(Thread):
|
|||
|
||||
|
||||
def run(self):
|
||||
# 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)
|
||||
with self.api.lock:
|
||||
|
||||
# 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))
|
||||
# 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)
|
||||
|
||||
# Direct Messages should match like /Home, above
|
||||
elif self.list_name == self.username + '/Direct Messages':
|
||||
statuses = dms_to_statuses(self.api.GetDirectMessages())
|
||||
# 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))
|
||||
|
||||
# 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)
|
||||
# Direct Messages should match like /Home, above
|
||||
elif self.list_name == self.username + '/Direct Messages':
|
||||
statuses = dms_to_statuses(self.api.GetDirectMessages())
|
||||
|
||||
# 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)
|
||||
# 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)
|
||||
|
||||
# Everything else is a straight search
|
||||
else:
|
||||
statuses = results_to_statuses(self.api.Search(self.list_name, rpp=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))
|
||||
|
||||
gtk.gdk.threads_enter()
|
||||
try:
|
||||
|
@ -64,7 +78,8 @@ class GetSingleTweet(Thread):
|
|||
|
||||
def run(self):
|
||||
statuses = []
|
||||
statuses.append(self.api.GetStatus(self.single_tweet))
|
||||
with self.api.lock:
|
||||
statuses.append(self.api.GetStatus(self.single_tweet))
|
||||
|
||||
gtk.gdk.threads_enter()
|
||||
try:
|
||||
|
@ -89,7 +104,8 @@ class GetFollowing(Thread):
|
|||
screen_name = re.sub('user: ', '', self.user)
|
||||
|
||||
try:
|
||||
relationship = self.api.ShowFriendships(target_screen_name=screen_name)
|
||||
with self.api.lock:
|
||||
relationship = self.api.ShowFriendships(target_screen_name=screen_name)
|
||||
following = relationship.source.following
|
||||
except HTTPError:
|
||||
following = false
|
||||
|
@ -112,7 +128,8 @@ class GetVerified(Thread):
|
|||
screen_name = re.sub('user: ', '', self.user)
|
||||
|
||||
try:
|
||||
user = self.api.GetUser(screen_name)
|
||||
with self.api.lock:
|
||||
user = self.api.GetUser(screen_name)
|
||||
verified = user.verified
|
||||
except HTTPError:
|
||||
verified = false
|
||||
|
|
25
mytwitter.py
25
mytwitter.py
|
@ -3,7 +3,6 @@
|
|||
# Custom twitter client... mostly for learning Python
|
||||
|
||||
import sys, ConfigParser, os, re, optparse, shelve
|
||||
import twitter
|
||||
import gtk, gtk.glade, gobject
|
||||
from urllib2 import HTTPError
|
||||
from twitterwidgets import TweetPane
|
||||
|
@ -47,7 +46,7 @@ class MyTwitter():
|
|||
for item in config.sections():
|
||||
if (re.match(r'account', item)):
|
||||
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.api = self.accounts[self.username]
|
||||
|
@ -106,8 +105,9 @@ class MyTwitter():
|
|||
# Add the tabs from last session to the notebook
|
||||
page_num = self.db['active_page']
|
||||
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.update_windows()
|
||||
|
||||
# Put Home, @user, Direct Messages, and lists in the View menu for
|
||||
# each user
|
||||
|
@ -188,7 +188,8 @@ class MyTwitter():
|
|||
def update_status(self):
|
||||
text = self.update_entry.get_text()
|
||||
self.update_entry.set_text("")
|
||||
self.api.PostUpdate(text, in_reply_to_status_id=self.reply_id)
|
||||
with self.api.lock:
|
||||
self.api.PostUpdate(text, in_reply_to_status_id=self.reply_id)
|
||||
self.reply_id = None
|
||||
self.update_status_bar('Tweet Posted')
|
||||
|
||||
|
@ -224,7 +225,8 @@ class MyTwitter():
|
|||
|
||||
|
||||
def on_retweet(self, widget, data):
|
||||
self.api.PostRetweet(data['id'])
|
||||
with self.api.lock:
|
||||
self.api.PostRetweet(data['id'])
|
||||
|
||||
|
||||
def on_reply_to(self, widget, data):
|
||||
|
@ -262,7 +264,7 @@ class MyTwitter():
|
|||
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
|
||||
for i in range(self.tweet_notebook.get_n_pages()):
|
||||
pane = self.tweet_notebook.get_nth_page(i)
|
||||
|
@ -308,8 +310,9 @@ class MyTwitter():
|
|||
pane=new_pane,
|
||||
single_tweet=single_tweet).start()
|
||||
|
||||
self.update_windows()
|
||||
self.tweet_notebook.set_current_page(-1) # switch to the new pane
|
||||
if update:
|
||||
self.update_windows()
|
||||
self.tweet_notebook.set_current_page(-1) # switch to the new pane
|
||||
|
||||
|
||||
def on_tab_change(self, event, page, page_num):
|
||||
|
@ -356,10 +359,12 @@ class MyTwitter():
|
|||
current_pane = self.tweet_notebook.get_nth_page(self.tweet_notebook.get_current_page())
|
||||
user_name = re.sub('^user: ', '', current_pane.get_list_name())
|
||||
if current_pane.get_following():
|
||||
self.api.DestroyFriendship(user_name)
|
||||
with self.api.lock:
|
||||
self.api.DestroyFriendship(user_name)
|
||||
current_pane.set_following(False)
|
||||
else:
|
||||
self.api.CreateFriendship(user_name)
|
||||
with self.api.lock:
|
||||
self.api.CreateFriendship(user_name)
|
||||
current_pane.set_following(True)
|
||||
|
||||
self.update_follow_button(current_pane)
|
||||
|
|
Reference in New Issue
Block a user