>>> ================================ RESTART ================================
>>>
testNewsStoryConstructor (__main__.ProblemSet5NewsStory) ... ok
testNewsStoryGetGuid (__main__.ProblemSet5NewsStory) ... ok
testNewsStoryGetLink (__main__.ProblemSet5NewsStory) ... ok
testNewsStoryGetSubject (__main__.ProblemSet5NewsStory) ... ok
testNewsStoryGetSummary (__main__.ProblemSet5NewsStory) ... ok
testNewsStoryGetTitle (__main__.ProblemSet5NewsStory) ... ok
test1TitleTrigger (__main__.ProblemSet5) ... ok
test2SubjectTrigger (__main__.ProblemSet5) ... ok
test3SummaryTrigger (__main__.ProblemSet5) ... ok
test4NotTrigger (__main__.ProblemSet5) ... ok
test5AndTrigger (__main__.ProblemSet5) ... ok
test6OrTrigger (__main__.ProblemSet5) ... ok
test7PhraseTrigger (__main__.ProblemSet5) ... ok
test8FilterStories (__main__.ProblemSet5) ... ok
test8FilterStories2 (__main__.ProblemSet5) ... ok
test9UserTriggers (__main__.ProblemSet5) ... found line!
# 6.00 Problem Set 5
# RSS Feed Filter
import feedparser
import string
import time
from project_util import translate_html
from news_gui import Popup
#-----------------------------------------------------------------------
#
# Problem Set 5
#======================
# Code for retrieving and parsing
# Google and Yahoo News feeds
# Do not change this code
#======================
def process(url):
"""
Fetches news items from the rss url and parses them.
Returns a list of NewsStory-s.
"""
feed = feedparser.parse(url)
entries = feed.entries
ret = []
for entry in entries:
guid = entry.guid
title = translate_html(entry.title)
link = entry.link
summary = translate_html(entry.summary)
try:
subject = translate_html(entry.tags[0]['term'])
except AttributeError:
subject = ""
newsStory = NewsStory(guid, title, subject, summary, link)
ret.append(newsStory)
return ret
#======================
# Part 1
# Data structure design
#======================
# Problem 1
class NewsStory(object):
def __init__(self, guid, title, subject, summary, link):
self.guid = guid
self.title = title
self.subject = subject
self.summary = summary
self.link = link
def get_guid(self):
return self.guid
def get_title(self):
return self.title
def get_subject(self):
return self.subject
def get_summary(self):
return self.summary
def get_link(self):
return self.link
#======================
# Part 2
# Triggers
#======================
class Trigger(object):
def evaluate(self, story):
"""
Returns True if an alert should be generated
for the given news item, or False otherwise.
"""
raise NotImplementedError
# Whole Word Triggers
# Problems 2-5
class WordTrigger(Trigger):
def __init__(self, word):
self.word = word.lower()
def is_word_in(self, text):
text = text.lower()
for e in string.punctuation :
if e in text: text = text.replace(e, " ")
return self.word in text.split()
class TitleTrigger(WordTrigger):
def evaluate(self, story):
return self.is_word_in(story.title)
class SubjectTrigger(WordTrigger):
def evaluate(self, story):
return self.is_word_in(story.subject)
class SummaryTrigger(WordTrigger):
def evaluate(self, story):
return self.is_word_in(story.summary)
# Composite Triggers
# Problems 6-8
class NotTrigger(Trigger):
def __init__(self, trigger):
self.trigger = trigger
def evaluate(self, story):
return not self.trigger.evaluate(story)
class AndTrigger(Trigger):
def __init__(self, trigger1, trigger2):
self.trigger1 = trigger1
self.trigger2 = trigger2
def evaluate(self, story):
return self.trigger1.evaluate(story) and self.trigger2.evaluate(story)
class OrTrigger(Trigger):
def __init__(self, trigger1, trigger2):
self.trigger1 = trigger1
self.trigger2 = trigger2
def evaluate(self, story):
return self.trigger1.evaluate(story) or self.trigger2.evaluate(story)
# Phrase Trigger
# Question 9
class PhraseTrigger(Trigger):
def __init__(self, phrase):
self.phrase = phrase
def evaluate(self, story):
return (self.phrase in story.title) or (self.phrase in story.subject) or (self.phrase in story.summary)
#======================
# Part 3
# Filtering
#======================
def filter_stories(stories, triggerlist):
"""
Takes in a list of NewsStory-s.
Returns only those stories for whom
a trigger in triggerlist fires.
"""
story_filter = []
for story in stories:
for trigger in triggerlist:
if trigger.evaluate(story) == True:
story_filter.append(story)
break
return story_filter
#======================
# Part 4
# User-Specified Triggers
#======================
def readTriggerConfig(filename):
"""
Returns a list of trigger objects
that correspond to the rules set
in the file filename
"""
triggerfile = open(filename, "r")
all = [ line.rstrip() for line in triggerfile.readlines() ]
lines = []
phrase = ""
triggers = {}
trigger_list = []
for line in all:
if len(line) == 0 or line[0] == '#':
continue
lines.append(line)
for i in range(len(lines)):
lines[i] = lines[i].split()
for e in lines:
if e[0] == "ADD":
for x in e[1:]:
trigger_list.append(triggers[x])
elif e[1] == "TITLE":
triggers[e[0]] = TitleTrigger(e[2])
elif e[1] == "SUBJECT":
triggers[e[0]] = SubjectTrigger(e[2])
elif e[1] == "SUMMARY":
triggers[e[0]] = SummaryTrigger(e[2])
elif e[1] == "NOT":
triggers[e[0]] = NotTrigger(triggers[e[2]])
elif e[1] == "AND":
triggers[e[0]] = AndTrigger(triggers[e[2]], triggers[e[3]])
elif e[1] == "OR":
triggers[e[0]] = OrTrigger(triggers[e[2]], triggers[e[3]])
elif e[1] == "PHRASE":
phrase = e[2]
for x in e[3:]:
phrase += " " + x
triggers[e[0]] = PhraseTrigger(phrase)
return trigger_list
import thread
def main_thread(p):
# A sample trigger list - you'll replace
# this with something more configurable in Problem 11
# t1 = SubjectTrigger("Obama")
# t2 = SummaryTrigger("MIT")
# t3 = PhraseTrigger("Supreme Court")
# t4 = OrTrigger(t2, t3)
# triggerlist = [t1, t4]
# TODO: Problem 11
# After implementing readTriggerConfig, uncomment this line
triggerlist = readTriggerConfig("triggers.txt")
print triggerlist
guidShown = []
while True:
print "Polling..."
# Get stories from Google's Top Stories RSS news feed
stories = process("http://news.google.com/?output=rss")
# Get stories from Yahoo's Top Stories RSS news feed
stories.extend(process("http://rss.news.yahoo.com/rss/topstories"))
# Only select stories we're interested in
stories = filter_stories(stories, triggerlist)
# Don't print a story if we have already printed it before
newstories = []
for story in stories:
if story.get_guid() not in guidShown:
newstories.append(story)
for story in newstories:
guidShown.append(story.get_guid())
p.newWindow(story)
print "Sleeping..."
time.sleep(SLEEPTIME)
SLEEPTIME = 60 #seconds -- how often we poll
class Trigger(object):
def evaluate():
return False
class WordTrigger(Trigger):
def __init__(self, word):
self.word = word.lower()
print "Injected!"
def hash(self):
raise NotImplementedError
class SubjectTrigger(Trigger):
def __init__(self, word):
self.word = word.lower()
print "Injected Subject!"
def hash(self):
return "SUBJECT-" + self.word
class TitleTrigger(WordTrigger):
def hash(self):
return "TITLE-" + self.word
class SummaryTrigger(WordTrigger):
def hash(self):
return "SUMMARY-" + self.word
class NotTrigger(Trigger):
def __init__(self, trigger):
self.trigger = trigger
print "Injected!"
def hash(self):
return "NOT-" + self.trigger.hash()
class PhraseTrigger(Trigger):
def __init__(self, phrase):
self.phrase = phrase
print "Injected!"
def hash(self):
return "PHRASE-" + self.phrase
class CompositeTrigger(Trigger):
def __init__(self, trigger1, trigger2):
self.trigger1 = trigger1
self.trigger2 = trigger2
class AndTrigger(CompositeTrigger):
def hash(self):
t1_hash = self.trigger1.hash()
t2_hash = self.trigger2.hash()
if t1_hash > t2_hash:
return "AND-" + t1_hash + "-" + t2_hash
else:
return "AND-" + t2_hash + "-" + t1_hash
class OrTrigger(CompositeTrigger):
def hash(self):
t1_hash = self.trigger1.hash()
t2_hash = self.trigger2.hash()
if t1_hash > t2_hash:
return "OR-" + t1_hash + "-" + t2_hash
else:
return "OR-" + t2_hash + "-" + t1_hash
Injected Subject!
Injected!
Injected!
{'SUBJECT-sports': False, 'OR-SUMMARY-obama-PHRASE-Hillary Clinton': False}
ERROR
======================================================================
ERROR: test9UserTriggers (__main__.ProblemSet5)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/sakh/MIT/6.00 Intro to CS/ps5/ps5_test.py", line 269, in test9UserTriggers
trigger_list = readTriggerConfig("triggers.txt")
File "compile-errors", line 205, in readTriggerConfig
NameError: global name 'TitleTrigger' is not defined
----------------------------------------------------------------------
Ran 16 tests in 0.495s
FAILED (errors=1)