First stab at implementing threads... seems to work okay, then suddenly segfaults
This commit is contained in:
parent
4eaf2549c2
commit
45b374f24f
110
apithreads.py
Normal file
110
apithreads.py
Normal file
|
@ -0,0 +1,110 @@
|
|||
# Python module that handles calls to the twitter API as a separate thread
|
||||
|
||||
import re
|
||||
from threading import Thread
|
||||
|
||||
class GetTweets(Thread):
|
||||
def __init__(self, api, list_name, pane, num_entries, username):
|
||||
Thread.__init__(self)
|
||||
self.api = api
|
||||
self.list_name = list_name
|
||||
self.pane = pane
|
||||
self.num_entries = num_entries
|
||||
self.username = username
|
||||
|
||||
|
||||
def run(self):
|
||||
print 'debug: GetTweets.run(): start'
|
||||
|
||||
# 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))
|
||||
|
||||
# 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)
|
||||
|
||||
# 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))
|
||||
|
||||
self.pane.update_window(statuses)
|
||||
|
||||
print 'debug: GetTweets.run(): finished'
|
||||
|
||||
|
||||
### End class GetTweets
|
||||
|
||||
|
||||
|
||||
# We use these classes to emulate a Status object when we need
|
||||
# one to be built out of something else.
|
||||
class Status():
|
||||
def __init__(self):
|
||||
self.user = User()
|
||||
self.id = None
|
||||
self.created_at = None
|
||||
self.in_reply_to_screen_name = None
|
||||
self.in_reply_to_status_id = None
|
||||
|
||||
|
||||
class User():
|
||||
def __init__(self):
|
||||
self.screen_name = None
|
||||
self.name = None
|
||||
|
||||
|
||||
# To keep things simple elsewhere and improve code reuse
|
||||
# we'll build a list of home-cooked Status objects out of results.
|
||||
# Why is this even necessary?
|
||||
# Why can't we have more consistency out of the Twitter API?
|
||||
def results_to_statuses(results):
|
||||
statuses = []
|
||||
for result in results.results:
|
||||
status = Status()
|
||||
status.id = result.id
|
||||
status.user = User()
|
||||
status.user.screen_name = result.from_user
|
||||
status.user.name = ""
|
||||
status.in_reply_to_screen_name = result.to_user
|
||||
# The Twitter Search API has different timestamps than the
|
||||
# REST API... balls
|
||||
# fixme:
|
||||
# Gotta be a cleaner way to do this, but I can't think of it
|
||||
# right now
|
||||
created_at = re.sub(',', '', result.created_at)
|
||||
created_split = re.split(' ', created_at)
|
||||
status.created_at = created_split[0] + ' ' + created_split[2] + ' ' + created_split[1] + ' ' + created_split[4] + ' ' + created_split[5] + ' ' + created_split[3]
|
||||
status.text = result.text
|
||||
statuses.append(status)
|
||||
return statuses
|
||||
|
||||
|
||||
def dms_to_statuses(direct_messages):
|
||||
statuses = []
|
||||
for dm in direct_messages:
|
||||
status = Status()
|
||||
status.id = dm.id
|
||||
status.user = User()
|
||||
status.user.screen_name = dm.sender_screen_name
|
||||
status.user.name = dm.sender.name
|
||||
status.created_at = dm.created_at
|
||||
status.text = dm.text
|
||||
statuses.append(status)
|
||||
return statuses
|
116
mytwitter.py
116
mytwitter.py
|
@ -7,6 +7,7 @@ import twitter
|
|||
import gtk, gtk.glade, gobject
|
||||
from urllib2 import HTTPError
|
||||
from twitterwidgets import TweetPane
|
||||
import apithreads
|
||||
|
||||
|
||||
class MyTwitter():
|
||||
|
@ -135,6 +136,7 @@ class MyTwitter():
|
|||
gobject.timeout_add(self.refresh_time * 1000, self.update_windows)
|
||||
|
||||
|
||||
# Spawns a thread for each pane, which updates that pane.
|
||||
def update_windows(self):
|
||||
for i in range(0, self.tweet_notebook.get_n_pages()):
|
||||
pane = self.tweet_notebook.get_nth_page(i)
|
||||
|
@ -144,41 +146,36 @@ class MyTwitter():
|
|||
if pane.get_single_tweet() is not None:
|
||||
continue
|
||||
|
||||
# username/Home entries need to load the appropriate Home feed
|
||||
elif re.search(r'/Home', list_name):
|
||||
account = self.accounts[re.sub(r'/Home', r'', list_name)]
|
||||
statuses = account.GetHomeTimeline(count=self.num_entries)
|
||||
# Determine username and appropriate account to use
|
||||
found = False
|
||||
|
||||
# For @username, we need to check if it is one of our usernames, or
|
||||
# just needs to be searched on
|
||||
elif re.match('@', list_name):
|
||||
if self.accounts.has_key(re.sub('@', '', list_name)):
|
||||
account = self.accounts[re.sub(r'@', r'', list_name)]
|
||||
statuses = account.GetMentions(count=self.num_entries)
|
||||
else:
|
||||
statuses = self.results_to_statuses(self.api.Search(list_name, rpp=self.num_entries))
|
||||
|
||||
# Direct Messages should match like /Home, above
|
||||
elif re.search(r'/Direct Messages', list_name):
|
||||
account = self.accounts[re.sub(r'/Direct Messages', r'', list_name)]
|
||||
statuses = self.dms_to_statuses(account.GetDirectMessages())
|
||||
|
||||
# User lookups go straight to the user
|
||||
elif re.match(r'user: ', list_name):
|
||||
statuses = self.api.GetUserTimeline(re.sub(r'^user: ', r'', list_name), count=self.num_entries)
|
||||
|
||||
# Lists load the appropriate list from the appropriate account
|
||||
elif re.match(r'list: ', list_name):
|
||||
username = re.sub(r'list: (.*)/.*', r'\1', list_name)
|
||||
real_list = re.sub(r'list: .*/(.*)', r'\1', list_name)
|
||||
username = re.sub('/Home', '', list_name)
|
||||
if self.accounts.has_key(username):
|
||||
account = self.accounts[username]
|
||||
statuses = account.GetListStatuses(real_list, per_page=self.num_entries)
|
||||
found = True
|
||||
|
||||
# Everything else is a straight search
|
||||
else:
|
||||
statuses = self.results_to_statuses(self.api.Search(list_name, rpp=self.num_entries))
|
||||
if not found:
|
||||
username = re.sub('@', '', list_name)
|
||||
if self.accounts.has_key(username):
|
||||
account = self.accounts[username]
|
||||
found = True
|
||||
|
||||
pane.update_window(statuses)
|
||||
if not found:
|
||||
username = re.sub('/Direct Messages', '', list_name)
|
||||
if self.accounts.has_key(username):
|
||||
account = self.accounts[username]
|
||||
found = True
|
||||
|
||||
if not found:
|
||||
account = self.api
|
||||
username = self.username
|
||||
|
||||
apithreads.GetTweets(api=account,
|
||||
list_name=list_name,
|
||||
pane=pane,
|
||||
num_entries=self.num_entries,
|
||||
username=username
|
||||
).start()
|
||||
|
||||
# We have to return true, so the timeout_add event will keep happening
|
||||
return True
|
||||
|
@ -440,69 +437,14 @@ class MyTwitter():
|
|||
self.username = new_user
|
||||
self.api = self.accounts[self.username]
|
||||
|
||||
|
||||
# To keep things simple elsewhere and improve code reuse
|
||||
# we'll build a list of home-cooked Status objects out of results.
|
||||
# Why is this even necessary?
|
||||
# Why can't we have more consistency out of the Twitter API?
|
||||
def results_to_statuses(self, results):
|
||||
statuses = []
|
||||
for result in results.results:
|
||||
status = Status()
|
||||
status.id = result.id
|
||||
status.user = User()
|
||||
status.user.screen_name = result.from_user
|
||||
status.user.name = ""
|
||||
status.in_reply_to_screen_name = result.to_user
|
||||
# The Twitter Search API has different timestamps than the
|
||||
# REST API... balls
|
||||
# fixme:
|
||||
# Gotta be a cleaner way to do this, but I can't think of it
|
||||
# right now
|
||||
created_at = re.sub(',', '', result.created_at)
|
||||
created_split = re.split(' ', created_at)
|
||||
status.created_at = created_split[0] + ' ' + created_split[2] + ' ' + created_split[1] + ' ' + created_split[4] + ' ' + created_split[5] + ' ' + created_split[3]
|
||||
status.text = result.text
|
||||
statuses.append(status)
|
||||
return statuses
|
||||
|
||||
|
||||
def dms_to_statuses(self, direct_messages):
|
||||
statuses = []
|
||||
for dm in direct_messages:
|
||||
status = Status()
|
||||
status.id = dm.id
|
||||
status.user = User()
|
||||
status.user.screen_name = dm.sender_screen_name
|
||||
status.user.name = dm.sender.name
|
||||
status.created_at = dm.created_at
|
||||
status.text = dm.text
|
||||
statuses.append(status)
|
||||
return statuses
|
||||
|
||||
### end class MyTwitter
|
||||
|
||||
|
||||
# We use these classes to emulate a Status object when we need
|
||||
# one to be built out of something else.
|
||||
class Status():
|
||||
def __init__(self):
|
||||
self.user = User()
|
||||
self.id = None
|
||||
self.created_at = None
|
||||
self.in_reply_to_screen_name = None
|
||||
self.in_reply_to_status_id = None
|
||||
|
||||
class User():
|
||||
def __init__(self):
|
||||
self.screen_name = None
|
||||
self.name = None
|
||||
|
||||
|
||||
# main
|
||||
parser = optparse.OptionParser()
|
||||
parser.add_option('-c' ,'--config', dest="filename", default="~/.mytwitter.conf")
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
my_twitter = MyTwitter(options.filename)
|
||||
gtk.gdk.threads_init()
|
||||
gtk.main()
|
||||
|
|
|
@ -70,6 +70,8 @@ class TweetPane(gtk.ScrolledWindow):
|
|||
|
||||
|
||||
def update_window(self, statuses):
|
||||
print 'debug: TweetPane.update_window(): ' + self.list_name
|
||||
|
||||
if self.updated_once is False:
|
||||
self.updated_once = True
|
||||
|
||||
|
|
Reference in New Issue
Block a user