Mercurial > pidgin
comparison finch/libgnt/pygnt/example/rss/gntrss.py @ 18728:3db31505e42f
Use pseudo-nonblocking stuff to update the feeds.
author | Sadrul Habib Chowdhury <imadil@gmail.com> |
---|---|
date | Tue, 31 Jul 2007 04:33:53 +0000 |
parents | 778f4fc8cbcc |
children | 6976a6dae441 |
comparison
equal
deleted
inserted
replaced
18727:778f4fc8cbcc | 18728:3db31505e42f |
---|---|
23 | 23 |
24 """ | 24 """ |
25 This file deals with the rss parsing part (feedparser) of the application | 25 This file deals with the rss parsing part (feedparser) of the application |
26 """ | 26 """ |
27 | 27 |
28 import threading | 28 import os |
29 import tempfile, urllib2 | |
29 import feedparser | 30 import feedparser |
30 import gobject | 31 import gobject |
31 import sys | 32 import sys |
32 import time | 33 import time |
33 | 34 |
44 __gsignals__ = { | 45 __gsignals__ = { |
45 'delete' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_OBJECT,)) | 46 'delete' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_OBJECT,)) |
46 } | 47 } |
47 def __init__(self, item, parent): | 48 def __init__(self, item, parent): |
48 self.__gobject_init__() | 49 self.__gobject_init__() |
49 self.date = item['date'] | 50 try: |
50 self.date_parsed = item['date_parsed'] | 51 "Apparently some feed items don't have any dates in them" |
52 self.date = item['date'] | |
53 self.date_parsed = item['date_parsed'] | |
54 except: | |
55 item['date'] = self.date = time.ctime() | |
56 self.date_parsed = feedparser._parse_date(self.date) | |
57 | |
51 self.title = item['title'] | 58 self.title = item['title'] |
52 self.summary = item['summary'] | 59 self.summary = item['summary'] |
53 self.link = item['link'] | 60 self.link = item['link'] |
54 self.parent = parent | 61 self.parent = parent |
55 self.unread = True | 62 self.unread = True |
109 self.url = url # The url of the feed itself | 116 self.url = url # The url of the feed itself |
110 self.link = url # The web page associated with the feed | 117 self.link = url # The web page associated with the feed |
111 self.desc = url | 118 self.desc = url |
112 self.title = url | 119 self.title = url |
113 self.unread = 0 | 120 self.unread = 0 |
114 self.timer = 0 | |
115 self.items = [] | 121 self.items = [] |
116 self.hash = {} | 122 self.hash = {} |
123 self.pending = False | |
117 | 124 |
118 def do_set_property(self, property, value): | 125 def do_set_property(self, property, value): |
119 if property.name == 'link': | 126 if property.name == 'link': |
120 self.link = value | 127 self.link = value |
121 elif property.name == 'desc': | 128 elif property.name == 'desc': |
124 self.title = value | 131 self.title = value |
125 elif property.name == 'unread': | 132 elif property.name == 'unread': |
126 self.unread = value | 133 self.unread = value |
127 pass | 134 pass |
128 | 135 |
129 def check_thread_for_death(self): | 136 def set_result(self, result): |
130 #if self.thread.running: | |
131 # sys.stderr.write(time.ctime() + "continue") | |
132 # return True | |
133 # The thread has ended!! | |
134 #result = self.thread.result | |
135 #self.thread = None | |
136 result = feedparser.parse(self.url) | |
137 # XXX Look at result['bozo'] first, and emit some signal that the UI can use | 137 # XXX Look at result['bozo'] first, and emit some signal that the UI can use |
138 # to indicate (dim the row?) that the feed has invalid XML format or something | 138 # to indicate (dim the row?) that the feed has invalid XML format or something |
139 | 139 |
140 channel = result['channel'] | 140 try: |
141 self.set_property('link', channel['link']) | 141 channel = result['channel'] |
142 self.set_property('desc', channel['description']) | 142 self.set_property('link', channel['link']) |
143 self.set_property('title', channel['title']) | 143 self.set_property('desc', channel['description']) |
144 self.timer = 0 | 144 self.set_property('title', channel['title']) |
145 items = result['items'] | 145 items = result['items'] |
146 except: | |
147 items = () | |
148 | |
146 tmp = {} | 149 tmp = {} |
147 for item in self.items: | 150 for item in self.items: |
148 tmp[hash(item)] = item | 151 tmp[hash(item)] = item |
149 | 152 |
150 unread = self.unread | 153 unread = self.unread |
162 for hv in tmp: | 165 for hv in tmp: |
163 tmp[hv].remove() | 166 tmp[hv].remove() |
164 | 167 |
165 if unread != self.unread: | 168 if unread != self.unread: |
166 self.set_property('unread', unread) | 169 self.set_property('unread', unread) |
170 self.pending = False | |
167 return False | 171 return False |
168 | 172 |
169 def refresh(self): | 173 def refresh(self): |
170 #if self.thread == 0: | 174 if self.pending: |
171 # self.thread = FeedReader(self) | 175 return |
172 # self.thread.start() | 176 self.pending = True |
173 if self.timer == 0: | 177 FeedReader(self).run() |
174 self.timer = gobject.timeout_add(1000, self.check_thread_for_death) | |
175 | 178 |
176 def mark_read(self): | 179 def mark_read(self): |
177 for item in self.items: | 180 for item in self.items: |
178 item.mark_unread(False) | 181 item.mark_unread(False) |
179 | 182 |
180 gobject.type_register(Feed) | 183 gobject.type_register(Feed) |
181 | 184 |
182 ## | 185 """ |
183 # A FeedReader class, which is threaded to make sure it doesn't freeze the ui | 186 The FeedReader updates a Feed. It fork()s off a child to avoid blocking. |
184 # (this thing doesn't quite work ... yet) | 187 """ |
185 ## | 188 class FeedReader: |
186 class FeedReader(threading.Thread): | |
187 def __init__(self, feed): | 189 def __init__(self, feed): |
188 self.feed = feed | 190 self.feed = feed |
189 self.running = True | 191 |
190 threading.Thread.__init__(self) | 192 def reap_child(self, pid, status): |
193 result = feedparser.parse(self.tmpfile.name) | |
194 self.tmpfile.close() | |
195 self.feed.set_result(result) | |
191 | 196 |
192 def run(self): | 197 def run(self): |
193 sys.stderr.write(str(time.ctime()) + " STARTED!!!\n\n\n") | 198 self.tmpfile = tempfile.NamedTemporaryFile() |
194 self.running = True | 199 self.pid = os.fork() |
195 self.result = feedparser.parse(self.feed.url) | 200 if self.pid == 0: |
196 self.running = False | 201 tmp = urllib2.urlopen(self.feed.url) |
197 sys.stderr.write(str(time.ctime()) + " DONE!!!\n\n\n") | 202 content = tmp.read() |
203 tmp.close() | |
204 self.tmpfile.write(content) | |
205 self.tmpfile.flush() | |
206 # Do NOT close tmpfile here | |
207 os._exit(os.EX_OK) | |
208 gobject.child_watch_add(self.pid, self.reap_child) | |
198 | 209 |
199 feeds = [] | 210 feeds = [] |
200 urls = ("http://rss.slashdot.org/Slashdot/slashdot", | 211 urls = ("http://rss.slashdot.org/Slashdot/slashdot", |
201 "http://www.python.org/channews.rdf", | 212 "http://kerneltrap.org/node/feed", |
202 "http://kerneltrap.org/node/feed" | 213 "http://pidgin.im/rss.php", |
214 "http://www.formula1.com/rss/news/latest.rss", | |
215 "http://www.pheedo.com/f/freshmeatnet_announcements_unix", | |
216 "http://www.cricinfo.com/rss/livescores.xml" | |
203 ) | 217 ) |
204 | 218 |
205 for url in urls: | 219 for url in urls: |
206 feed = Feed(url) | 220 feed = Feed(url) |
207 feeds.append(feed) | 221 feeds.append(feed) |