diff --git a/examples/opml-top100.ini b/examples/opml-top100.ini index be6fec1..34abd64 100644 --- a/examples/opml-top100.ini +++ b/examples/opml-top100.ini @@ -28,12 +28,11 @@ items_per_page = 60 activity_threshold = 90 -# Reading lists, one per line, indented -reading_lists = - http://share.opml.org/opml/top100.opml - filters = excerpt.py [excerpt.py] omit = img p br width = 500 + +[http://share.opml.org/opml/top100.opml] +content_type = opml diff --git a/planet/config.py b/planet/config.py index bdcc8cb..6679abc 100644 --- a/planet/config.py +++ b/planet/config.py @@ -103,12 +103,12 @@ def __init__(): define_planet_list('template_directories') define_planet_list('filters') define_planet_list('filter_directories') - define_planet_list('reading_lists') # template options define_tmpl_int('days_per_page', 0) define_tmpl_int('items_per_page', 60) define_tmpl('encoding', 'utf-8') + define_tmpl('content_type', 'utf-8') def load(config_file): """ initialize and load a configuration""" @@ -117,7 +117,7 @@ def load(config_file): parser.read(config_file) import config, planet - from planet import opml + from planet import opml, foaf log = planet.getLogger(config.log_level()) # Theme support @@ -173,7 +173,10 @@ def load(config_file): # read once to verify data=StringIO.StringIO(urllib.urlopen(list).read()) cached_config = ConfigParser() - opml.opml2config(data, cached_config) + if content_type(list).find('opml')>=0: + opml.opml2config(data, cached_config) + elif content_type(list).find('foaf')>=0: + foaf.foaf2config(data, cached_config) if not cached_config.sections(): raise Exception # write to cache @@ -184,7 +187,7 @@ def load(config_file): # re-parse and proceed log.debug("Using %s readinglist", list) data.seek(0) - opml.opml2config(data, parser) + parser.read(cache_filename) except: try: parser.read(cache_filename) @@ -226,7 +229,18 @@ def feedtype(): def subscriptions(): """ list the feed subscriptions """ return filter(lambda feed: feed!='Planet' and - feed not in template_files()+filters(), parser.sections()) + feed not in template_files()+filters()+reading_lists(), + parser.sections()) + +def reading_lists(): + """ list of lists of feed subscriptions """ + result = [] + for section in parser.sections(): + if parser.has_option(section, 'content_type'): + type = parser.get(section, 'content_type') + if type.find('opml')>=0 or type.find('foaf')>=0: + result.append(section) + return result def planet_options(): """ dictionary of planet wide options""" diff --git a/planet/foaf.py b/planet/foaf.py new file mode 100644 index 0000000..d2d2439 --- /dev/null +++ b/planet/foaf.py @@ -0,0 +1,56 @@ +from ConfigParser import ConfigParser + +# input = foaf, output = ConfigParser +def foaf2config(rdf, baseuri, config=None): + + if not config: + config = ConfigParser() + + try: + from RDF import Model, NS, Parser, Statement + except: + return config + + if hasattr(rdf, 'read'): + rdf = rdf.read() + + model = Model() + def handler(code, level, facility, message, line, column, byte, file, uri): + pass + Parser().parse_string_into_model(model,rdf,baseuri,handler) + + dc = NS('http://purl.org/dc/elements/1.1/') + foaf = NS('http://xmlns.com/foaf/0.1/') + rdfs = NS('http://www.w3.org/2000/01/rdf-schema#') + + for statement in model.find_statements(Statement(None,foaf.weblog,None)): + feed = model.get_target(statement.object,rdfs.seeAlso) + if not feed: continue + + title = model.get_target(statement.subject,foaf.name) + if not title: title = model.get_target(statement.object,dc.title) + if not title: continue + + feed = str(feed.uri) + if not config.has_section(feed): + config.add_section(feed) + config.set(feed, 'name', str(title)) + + return config + +if __name__ == "__main__": + import sys, urllib + config = ConfigParser() + + for uri in sys.argv[1:]: + foaf2config(urllib.urlopen(uri), uri, config) + + config.write(sys.stdout) + +if __name__ == "__main__": + # small main program which converts FOAF into config.ini format + import sys, urllib + config = ConfigParser() + for foaf in sys.argv[1:]: + foaf2config(urllib.urlopen(foaf), config) + config.write(sys.stdout) diff --git a/planet/opml.py b/planet/opml.py index 3453f83..d4e9a54 100755 --- a/planet/opml.py +++ b/planet/opml.py @@ -140,3 +140,11 @@ cp1252 = { unichr(156): unichr( 339), # latin small ligature oe unichr(158): unichr( 382), # latin small letter z with caron unichr(159): unichr( 376)} # latin capital letter y with diaeresis + +if __name__ == "__main__": + # small main program which converts OPML into config.ini format + import sys, urllib + config = ConfigParser() + for opml in sys.argv[1:]: + opml2config(urllib.urlopen(opml), config) + config.write(sys.stdout) diff --git a/tests/data/config/rlist.ini b/tests/data/config/rlist.ini index b47b2b9..595f0c6 100644 --- a/tests/data/config/rlist.ini +++ b/tests/data/config/rlist.ini @@ -2,4 +2,6 @@ name = Test Configuration output_theme = asf cache_directory = tests/work/config/cache -reading_lists = tests/data/config/opml.xml + +[tests/data/config/opml.xml] +content_type = opml diff --git a/tests/test_foaf.py b/tests/test_foaf.py new file mode 100644 index 0000000..4d635f2 --- /dev/null +++ b/tests/test_foaf.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python + +import unittest +from planet.foaf import foaf2config +from ConfigParser import ConfigParser + +blogroll = 'http://journal.dajobe.org/journal/2003/07/semblogs/bloggers.rdf' +testfeed = "http://dannyayers.com/feed/rdf" +test_foaf_document = ''' + + + +Danny Ayers + + + +Raw Blog by Danny Ayers + + + + + + + + + + + + + + +'''.strip() + +class FoafTest(unittest.TestCase): + """ + Test the foaf2config function + """ + + def setUp(self): + self.config = ConfigParser() + + # + # Tests + # + + def test_foaf_document(self): + foaf2config(test_foaf_document, blogroll, self.config) + self.assertEqual('Danny Ayers', self.config.get(testfeed, 'name')) + + def test_no_foaf_name(self): + test = test_foaf_document.replace('foaf:name','foaf:title') + foaf2config(test, blogroll, self.config) + self.assertEqual('Raw Blog by Danny Ayers', + self.config.get(testfeed, 'name')) + + def test_no_weblog(self): + test = test_foaf_document.replace('rdfs:seeAlso','rdfs:seealso') + foaf2config(test, blogroll, self.config) + self.assertFalse(self.config.has_section(testfeed)) + + def test_invalid_xml_before(self): + test = '\n' + test_foaf_document + foaf2config(test, blogroll, self.config) + self.assertFalse(self.config.has_section(testfeed)) + + def test_invalid_xml_after(self): + test = test_foaf_document.strip()[:-1] + foaf2config(test, blogroll, self.config) + self.assertEqual('Danny Ayers', self.config.get(testfeed, 'name')) + +if __name__ == '__main__': + unittest.main()