Added extension support and converted PodcastGenerator to extension
This commit is contained in:
parent
e9eb3b5e95
commit
840dc7e5b8
8 changed files with 200 additions and 78 deletions
|
@ -9,7 +9,6 @@
|
||||||
'''
|
'''
|
||||||
|
|
||||||
from feedgen.feed import FeedGenerator
|
from feedgen.feed import FeedGenerator
|
||||||
from feedgen.podcast import PodcastGenerator
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,7 +31,7 @@ if __name__ == '__main__':
|
||||||
|
|
||||||
arg = sys.argv[1]
|
arg = sys.argv[1]
|
||||||
|
|
||||||
fg = PodcastGenerator() if arg.endswith('podcast') else FeedGenerator()
|
fg = FeedGenerator()
|
||||||
fg.id('http://lernfunk.de/_MEDIAID_123')
|
fg.id('http://lernfunk.de/_MEDIAID_123')
|
||||||
fg.title('Testfeed')
|
fg.title('Testfeed')
|
||||||
fg.author( {'name':'Lars Kiesow','email':'lkiesow@uos.de'} )
|
fg.author( {'name':'Lars Kiesow','email':'lkiesow@uos.de'} )
|
||||||
|
@ -64,16 +63,21 @@ if __name__ == '__main__':
|
||||||
elif arg == 'rss':
|
elif arg == 'rss':
|
||||||
print fg.rss_str(pretty=True)
|
print fg.rss_str(pretty=True)
|
||||||
elif arg == 'podcast':
|
elif arg == 'podcast':
|
||||||
fg.itunes_author('Lars Kiesow')
|
# Load the podcast extension. It will automatically be loaded for all
|
||||||
fg.itunes_category('Technology', 'Podcasting')
|
# entries in the feed, too. Thus also for our “fe”.
|
||||||
fg.itunes_explicit('no')
|
fg.load_extension('podcast')
|
||||||
fg.itunes_complete('no')
|
fg.podcast.itunes_author('Lars Kiesow')
|
||||||
fg.itunes_new_feed_url('http://example.com/new-feed.rss')
|
fg.podcast.itunes_category('Technology', 'Podcasting')
|
||||||
fg.itunes_owner('John Doe', 'john@example.com')
|
fg.podcast.itunes_explicit('no')
|
||||||
fg.itunes_summary('Lorem ipsum dolor sit amet, consectetur adipiscing elit. Verba tu fingas et ea dicas, quae non sentias?')
|
fg.podcast.itunes_complete('no')
|
||||||
fe.itunes_author('Lars Kiesow')
|
fg.podcast.itunes_new_feed_url('http://example.com/new-feed.rss')
|
||||||
|
fg.podcast.itunes_owner('John Doe', 'john@example.com')
|
||||||
|
fg.podcast.itunes_summary('Lorem ipsum dolor sit amet, ' + \
|
||||||
|
'consectetur adipiscing elit. ' + \
|
||||||
|
'Verba tu fingas et ea dicas, quae non sentias?')
|
||||||
|
fe.podcast.itunes_author('Lars Kiesow')
|
||||||
|
|
||||||
print fg.podcast_str(pretty=True)
|
print fg.rss_str(pretty=True)
|
||||||
elif arg.endswith('atom'):
|
elif arg.endswith('atom'):
|
||||||
fg.atom_file(arg)
|
fg.atom_file(arg)
|
||||||
elif arg.endswith('rss'):
|
elif arg.endswith('rss'):
|
||||||
|
|
|
@ -50,8 +50,11 @@ class FeedEntry(object):
|
||||||
__rss_source = None
|
__rss_source = None
|
||||||
__rss_title = None
|
__rss_title = None
|
||||||
|
|
||||||
|
# Extension list:
|
||||||
|
__extensions = {}
|
||||||
|
|
||||||
def atom_entry(self, feed):
|
|
||||||
|
def atom_entry(self, feed, extensions=True):
|
||||||
'''Insert an ATOM entry into a existing XML structure. Normally you
|
'''Insert an ATOM entry into a existing XML structure. Normally you
|
||||||
would pass the feed node of an ATOM feed XML to this function.
|
would pass the feed node of an ATOM feed XML to this function.
|
||||||
|
|
||||||
|
@ -139,10 +142,15 @@ class FeedEntry(object):
|
||||||
rights = etree.SubElement(feed, 'rights')
|
rights = etree.SubElement(feed, 'rights')
|
||||||
rights.text = self.__atom_rights
|
rights.text = self.__atom_rights
|
||||||
|
|
||||||
|
if extensions:
|
||||||
|
for ext in self.__extensions.values() or []:
|
||||||
|
if ext.get('atom'):
|
||||||
|
entry = ext['inst'].extend_atom(entry)
|
||||||
|
|
||||||
return entry
|
return entry
|
||||||
|
|
||||||
|
|
||||||
def rss_entry(self, feed):
|
def rss_entry(self, feed, extensions=True):
|
||||||
'''Insert an RSS item into a existing XML structure. Normally you
|
'''Insert an RSS item into a existing XML structure. Normally you
|
||||||
would pass the channel node of an RSS feed XML to this function.
|
would pass the channel node of an RSS feed XML to this function.
|
||||||
|
|
||||||
|
@ -184,6 +192,12 @@ class FeedEntry(object):
|
||||||
pubDate = etree.SubElement(channel, 'pubDate')
|
pubDate = etree.SubElement(channel, 'pubDate')
|
||||||
pubDate.text = self.__rss_pubDate.strftime(
|
pubDate.text = self.__rss_pubDate.strftime(
|
||||||
'%a, %e %b %Y %H:%M:%S %z')
|
'%a, %e %b %Y %H:%M:%S %z')
|
||||||
|
|
||||||
|
if extensions:
|
||||||
|
for ext in self.__extensions.values() or []:
|
||||||
|
if ext.get('rss'):
|
||||||
|
entry = ext['inst'].extend_rss(entry)
|
||||||
|
|
||||||
return entry
|
return entry
|
||||||
|
|
||||||
|
|
||||||
|
@ -575,3 +589,34 @@ class FeedEntry(object):
|
||||||
if not ttl is None:
|
if not ttl is None:
|
||||||
self.__rss_ttl = int(ttl)
|
self.__rss_ttl = int(ttl)
|
||||||
return self.__rss_ttl
|
return self.__rss_ttl
|
||||||
|
|
||||||
|
|
||||||
|
def load_extension(self, name, atom=True, rss=True):
|
||||||
|
'''Load a specific extension by name.
|
||||||
|
|
||||||
|
:param name: Name of the extension to load.
|
||||||
|
:param atom: If the extension should be used for ATOM feeds.
|
||||||
|
:param rss: If the extension should be used for RSS feeds.
|
||||||
|
'''
|
||||||
|
# Check loaded extensions
|
||||||
|
if not isinstance(self.__extensions, dict):
|
||||||
|
self.__extensions = {}
|
||||||
|
if name in self.__extensions.keys():
|
||||||
|
raise ImportError('Extension already loaded')
|
||||||
|
|
||||||
|
# Load extension
|
||||||
|
extname = name[0].upper() + name[1:] + 'EntryExtension'
|
||||||
|
|
||||||
|
# Try to import extension from dedicated module for entry:
|
||||||
|
try:
|
||||||
|
supmod = __import__('feedgen.ext.%s_entry' % name)
|
||||||
|
extmod = getattr(supmod.ext, name + '_entry')
|
||||||
|
except ImportError:
|
||||||
|
# Try the FeedExtension module instead
|
||||||
|
supmod = __import__('feedgen.ext.%s' % name)
|
||||||
|
extmod = getattr(supmod.ext, name)
|
||||||
|
|
||||||
|
ext = getattr(extmod, extname)
|
||||||
|
extinst = ext()
|
||||||
|
setattr(self, name, extinst)
|
||||||
|
self.__extensions[name] = {'inst':extinst,'atom':atom,'rss':rss}
|
||||||
|
|
6
feedgen/ext/__init__.py
Normal file
6
feedgen/ext/__init__.py
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
===========
|
||||||
|
feedgen.ext
|
||||||
|
===========
|
||||||
|
"""
|
39
feedgen/ext/base.py
Normal file
39
feedgen/ext/base.py
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
'''
|
||||||
|
feedgen.ext.base
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Basic FeedGenerator which does nothing but provides all necessary methods.
|
||||||
|
|
||||||
|
:copyright: 2013, Lars Kiesow <lkiesow@uos.de>
|
||||||
|
|
||||||
|
:license: FreeBSD and LGPL, see license.* for more details.
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
class BaseExtension(object):
|
||||||
|
'''Basic FeedGenerator extension.
|
||||||
|
'''
|
||||||
|
|
||||||
|
def extend_rss(self, feed):
|
||||||
|
'''Create an RSS feed xml structure containing all previously set fields.
|
||||||
|
|
||||||
|
:param feed: The feed xml root element.
|
||||||
|
:returns: The feed root element.
|
||||||
|
'''
|
||||||
|
return feed
|
||||||
|
|
||||||
|
|
||||||
|
def extend_atom(self, feed, doc=None):
|
||||||
|
'''Create an ATOM feed xml structure containing all previously set
|
||||||
|
fields.
|
||||||
|
|
||||||
|
:param feed: The feed xml root element.
|
||||||
|
:returns: The feed root element.
|
||||||
|
'''
|
||||||
|
return feed, doc
|
||||||
|
|
||||||
|
|
||||||
|
class BaseEntryExtension(BaseExtension):
|
||||||
|
'''Basic FeedEntry extension.
|
||||||
|
'''
|
|
@ -14,12 +14,11 @@ from lxml import etree
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import dateutil.parser
|
import dateutil.parser
|
||||||
import dateutil.tz
|
import dateutil.tz
|
||||||
from feedgen.feed import FeedGenerator
|
from feedgen.ext.base import BaseExtension
|
||||||
from feedgen.podcast_entry import PodcastEntry
|
|
||||||
from feedgen.util import ensure_format
|
from feedgen.util import ensure_format
|
||||||
|
|
||||||
|
|
||||||
class PodcastGenerator(FeedGenerator):
|
class PodcastExtension(BaseExtension):
|
||||||
'''FeedGenerator extension for podcasts.
|
'''FeedGenerator extension for podcasts.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
@ -40,21 +39,18 @@ class PodcastGenerator(FeedGenerator):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def __create_podcast(self):
|
def extend_rss(self, rss_feed):
|
||||||
'''Create an RSS feed xml structure containing all previously set fields.
|
'''Create an RSS feed xml structure containing all previously set fields.
|
||||||
|
|
||||||
:returns: Tuple containing the feed root element and the element tree.
|
:returns: Tuple containing the feed root element and the element tree.
|
||||||
'''
|
'''
|
||||||
rss_feed, _ = super(PodcastGenerator,self)._create_rss()
|
|
||||||
ITUNES_NS = 'http://www.itunes.com/dtds/podcast-1.0.dtd'
|
ITUNES_NS = 'http://www.itunes.com/dtds/podcast-1.0.dtd'
|
||||||
# Replace the root element to add the itunes namespace
|
# Replace the root element to add the itunes namespace
|
||||||
feed = etree.Element('rss', version='2.0',
|
nsmap = rss_feed.nsmap
|
||||||
nsmap={
|
nsmap['itunes'] = ITUNES_NS
|
||||||
'atom' :'http://www.w3.org/2005/Atom',
|
feed = etree.Element('rss', version='2.0', nsmap=nsmap )
|
||||||
'itunes':ITUNES_NS} )
|
|
||||||
feed[:] = rss_feed[:]
|
feed[:] = rss_feed[:]
|
||||||
channel = feed[0]
|
channel = feed[0]
|
||||||
doc = etree.ElementTree(feed)
|
|
||||||
|
|
||||||
if self.__itunes_author:
|
if self.__itunes_author:
|
||||||
author = etree.SubElement(channel, '{%s}author' % ITUNES_NS)
|
author = etree.SubElement(channel, '{%s}author' % ITUNES_NS)
|
||||||
|
@ -102,28 +98,7 @@ class PodcastGenerator(FeedGenerator):
|
||||||
summary = etree.SubElement(channel, '{%s}summary' % ITUNES_NS)
|
summary = etree.SubElement(channel, '{%s}summary' % ITUNES_NS)
|
||||||
summary.text = self.__itunes_summary
|
summary.text = self.__itunes_summary
|
||||||
|
|
||||||
return feed, doc
|
return feed
|
||||||
|
|
||||||
|
|
||||||
def podcast_str(self, pretty=False):
|
|
||||||
'''Generates an RSS feed and returns the feed XML as string.
|
|
||||||
|
|
||||||
:param pretty: If the feed should be split into multiple lines and
|
|
||||||
properly indented.
|
|
||||||
:returns: String representation of the RSS feed.
|
|
||||||
'''
|
|
||||||
feed, doc = self.__create_podcast()
|
|
||||||
return etree.tostring(feed, pretty_print=pretty)
|
|
||||||
|
|
||||||
|
|
||||||
def podcast_file(self, filename):
|
|
||||||
'''Generates an RSS feed and write the resulting XML to a file.
|
|
||||||
|
|
||||||
:param filename: Name of file to write.
|
|
||||||
'''
|
|
||||||
feed, doc = self.__create_podcast()
|
|
||||||
with open(filename, 'w') as f:
|
|
||||||
doc.write(f)
|
|
||||||
|
|
||||||
|
|
||||||
def itunes_author(self, itunes_author=None):
|
def itunes_author(self, itunes_author=None):
|
||||||
|
@ -313,20 +288,6 @@ class PodcastGenerator(FeedGenerator):
|
||||||
return self.__itunes_summary
|
return self.__itunes_summary
|
||||||
|
|
||||||
|
|
||||||
def add_entry(self, podcastEntry=None):
|
|
||||||
'''This method will add a new entry to the podcast. If the podcastEntry
|
|
||||||
argument is omittet a new PodcstEntry object is created automatically.
|
|
||||||
This is the prefered way to add new entries to a feed.
|
|
||||||
|
|
||||||
:param podcastEntry: PodcastEntry object to add.
|
|
||||||
:returns: PodcastEntry object created or passed to this function.
|
|
||||||
'''
|
|
||||||
if podcastEntry is None:
|
|
||||||
podcastEntry = PodcastEntry()
|
|
||||||
super(PodcastGenerator, self).add_entry( podcastEntry )
|
|
||||||
return podcastEntry
|
|
||||||
|
|
||||||
|
|
||||||
_itunes_categories = {
|
_itunes_categories = {
|
||||||
'Arts': [ 'Design', 'Fashion & Beauty', 'Food', 'Literature',
|
'Arts': [ 'Design', 'Fashion & Beauty', 'Food', 'Literature',
|
||||||
'Performing Arts', 'Visual Arts' ],
|
'Performing Arts', 'Visual Arts' ],
|
|
@ -14,11 +14,11 @@ from lxml import etree
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import dateutil.parser
|
import dateutil.parser
|
||||||
import dateutil.tz
|
import dateutil.tz
|
||||||
from feedgen.entry import FeedEntry
|
from feedgen.ext.base import BaseExtension
|
||||||
from feedgen.util import ensure_format
|
from feedgen.util import ensure_format
|
||||||
|
|
||||||
|
|
||||||
class PodcastEntry(FeedEntry):
|
class PodcastEntryExtension(BaseExtension):
|
||||||
'''FeedEntry extension for podcasts.
|
'''FeedEntry extension for podcasts.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
@ -36,13 +36,11 @@ class PodcastEntry(FeedEntry):
|
||||||
__itunes_summary = None
|
__itunes_summary = None
|
||||||
|
|
||||||
|
|
||||||
def rss_entry(self, feed):
|
def extend_rss(self, entry):
|
||||||
'''Insert an RSS item into a existing XML structure. Normally you
|
'''Add additional fields to an RSS item.
|
||||||
would pass the channel node of an RSS feed XML to this function.
|
|
||||||
|
|
||||||
:param feed: The XML element to use as parent node for the item.
|
:param feed: The RSS item XML element to use.
|
||||||
'''
|
'''
|
||||||
entry = super(PodcastEntry,self).rss_entry(feed)
|
|
||||||
ITUNES_NS = 'http://www.itunes.com/dtds/podcast-1.0.dtd'
|
ITUNES_NS = 'http://www.itunes.com/dtds/podcast-1.0.dtd'
|
||||||
|
|
||||||
if self.__itunes_author:
|
if self.__itunes_author:
|
|
@ -69,9 +69,12 @@ class FeedGenerator(object):
|
||||||
__rss_ttl = None
|
__rss_ttl = None
|
||||||
__rss_webMaster = None
|
__rss_webMaster = None
|
||||||
|
|
||||||
|
# Extension list:
|
||||||
|
__extensions = {}
|
||||||
|
|
||||||
|
|
||||||
def _create_atom(self):
|
|
||||||
|
def _create_atom(self, extensions=True):
|
||||||
'''Create a ATOM feed xml structure containing all previously set fields.
|
'''Create a ATOM feed xml structure containing all previously set fields.
|
||||||
|
|
||||||
:returns: Tuple containing the feed root element and the element tree.
|
:returns: Tuple containing the feed root element and the element tree.
|
||||||
|
@ -81,7 +84,6 @@ class FeedGenerator(object):
|
||||||
feed.attrib['{http://www.w3.org/XML/1998/namespace}lang'] = \
|
feed.attrib['{http://www.w3.org/XML/1998/namespace}lang'] = \
|
||||||
self.__atom_feed_xml_lang
|
self.__atom_feed_xml_lang
|
||||||
|
|
||||||
doc = etree.ElementTree(feed)
|
|
||||||
if not ( self.__atom_id and self.__atom_title and self.__atom_updated ):
|
if not ( self.__atom_id and self.__atom_title and self.__atom_updated ):
|
||||||
raise ValueError('Required fields not set')
|
raise ValueError('Required fields not set')
|
||||||
id = etree.SubElement(feed, 'id')
|
id = etree.SubElement(feed, 'id')
|
||||||
|
@ -165,41 +167,50 @@ class FeedGenerator(object):
|
||||||
subtitle = etree.SubElement(feed, 'subtitle')
|
subtitle = etree.SubElement(feed, 'subtitle')
|
||||||
subtitle.text = self.__atom_subtitle
|
subtitle.text = self.__atom_subtitle
|
||||||
|
|
||||||
|
if extensions:
|
||||||
|
for ext in self.__extensions.values() or []:
|
||||||
|
if ext.get('atom'):
|
||||||
|
feed = ext['inst'].extend_atom(feed)
|
||||||
|
|
||||||
for entry in self.__feed_entries:
|
for entry in self.__feed_entries:
|
||||||
entry.atom_entry(feed)
|
entry.atom_entry(feed)
|
||||||
|
|
||||||
|
doc = etree.ElementTree(feed)
|
||||||
return feed, doc
|
return feed, doc
|
||||||
|
|
||||||
|
|
||||||
def atom_str(self, pretty=False):
|
def atom_str(self, pretty=False, extensions=True):
|
||||||
'''Generates an ATOM feed and returns the feed XML as string.
|
'''Generates an ATOM feed and returns the feed XML as string.
|
||||||
|
|
||||||
:param pretty: If the feed should be split into multiple lines and
|
:param pretty: If the feed should be split into multiple lines and
|
||||||
properly indented.
|
properly indented.
|
||||||
|
:param extensions: Enable or disable the loaded extensions for the xml
|
||||||
|
generation (default: enabled).
|
||||||
:returns: String representation of the ATOM feed.
|
:returns: String representation of the ATOM feed.
|
||||||
'''
|
'''
|
||||||
feed, doc = self._create_atom()
|
feed, doc = self._create_atom(extensions=extensions)
|
||||||
return etree.tostring(feed, pretty_print=pretty)
|
return etree.tostring(feed, pretty_print=pretty)
|
||||||
|
|
||||||
|
|
||||||
def atom_file(self, filename):
|
def atom_file(self, filename, extensions=True):
|
||||||
'''Generates an ATOM feed and write the resulting XML to a file.
|
'''Generates an ATOM feed and write the resulting XML to a file.
|
||||||
|
|
||||||
:param filename: Name of file to write.
|
:param filename: Name of file to write.
|
||||||
|
:param extensions: Enable or disable the loaded extensions for the xml
|
||||||
|
generation (default: enabled).
|
||||||
'''
|
'''
|
||||||
feed, doc = self._create_atom()
|
feed, doc = self._create_atom(extensions=extensions)
|
||||||
with open(filename, 'w') as f:
|
with open(filename, 'w') as f:
|
||||||
doc.write(f)
|
doc.write(f)
|
||||||
|
|
||||||
|
|
||||||
def _create_rss(self):
|
def _create_rss(self, extensions=True):
|
||||||
'''Create an RSS feed xml structure containing all previously set fields.
|
'''Create an RSS feed xml structure containing all previously set fields.
|
||||||
|
|
||||||
:returns: Tuple containing the feed root element and the element tree.
|
:returns: Tuple containing the feed root element and the element tree.
|
||||||
'''
|
'''
|
||||||
feed = etree.Element('rss', version='2.0',
|
feed = etree.Element('rss', version='2.0',
|
||||||
nsmap={'atom': 'http://www.w3.org/2005/Atom'} )
|
nsmap={'atom': 'http://www.w3.org/2005/Atom'} )
|
||||||
doc = etree.ElementTree(feed)
|
|
||||||
channel = etree.SubElement(feed, 'channel')
|
channel = etree.SubElement(feed, 'channel')
|
||||||
if not ( self.__rss_title and self.__rss_link and self.__rss_description ):
|
if not ( self.__rss_title and self.__rss_link and self.__rss_description ):
|
||||||
raise ValueError('Required fields not set')
|
raise ValueError('Required fields not set')
|
||||||
|
@ -306,29 +317,39 @@ class FeedGenerator(object):
|
||||||
webMaster = etree.SubElement(channel, 'webMaster')
|
webMaster = etree.SubElement(channel, 'webMaster')
|
||||||
webMaster.text = self.__rss_webMaster
|
webMaster.text = self.__rss_webMaster
|
||||||
|
|
||||||
|
if extensions:
|
||||||
|
for ext in self.__extensions.values() or []:
|
||||||
|
if ext.get('rss'):
|
||||||
|
feed = ext['inst'].extend_rss(feed)
|
||||||
|
|
||||||
for entry in self.__feed_entries:
|
for entry in self.__feed_entries:
|
||||||
entry.rss_entry(channel)
|
entry.rss_entry(channel)
|
||||||
|
|
||||||
|
doc = etree.ElementTree(feed)
|
||||||
return feed, doc
|
return feed, doc
|
||||||
|
|
||||||
|
|
||||||
def rss_str(self, pretty=False):
|
def rss_str(self, pretty=False, extensions=True):
|
||||||
'''Generates an RSS feed and returns the feed XML as string.
|
'''Generates an RSS feed and returns the feed XML as string.
|
||||||
|
|
||||||
:param pretty: If the feed should be split into multiple lines and
|
:param pretty: If the feed should be split into multiple lines and
|
||||||
properly indented.
|
properly indented.
|
||||||
|
:param extensions: Enable or disable the loaded extensions for the xml
|
||||||
|
generation (default: enabled).
|
||||||
:returns: String representation of the RSS feed.
|
:returns: String representation of the RSS feed.
|
||||||
'''
|
'''
|
||||||
feed, doc = self._create_rss()
|
feed, doc = self._create_rss(extensions=extensions)
|
||||||
return etree.tostring(feed, pretty_print=pretty)
|
return etree.tostring(feed, pretty_print=pretty)
|
||||||
|
|
||||||
|
|
||||||
def rss_file(self, filename):
|
def rss_file(self, filename, extensions=True):
|
||||||
'''Generates an RSS feed and write the resulting XML to a file.
|
'''Generates an RSS feed and write the resulting XML to a file.
|
||||||
|
|
||||||
:param filename: Name of file to write.
|
:param filename: Name of file to write.
|
||||||
|
:param extensions: Enable or disable the loaded extensions for the xml
|
||||||
|
generation (default: enabled).
|
||||||
'''
|
'''
|
||||||
feed, doc = self._create_rss()
|
feed, doc = self._create_rss(extensions=extensions)
|
||||||
with open(filename, 'w') as f:
|
with open(filename, 'w') as f:
|
||||||
doc.write(f)
|
doc.write(f)
|
||||||
|
|
||||||
|
@ -916,6 +937,14 @@ class FeedGenerator(object):
|
||||||
'''
|
'''
|
||||||
if feedEntry is None:
|
if feedEntry is None:
|
||||||
feedEntry = FeedEntry()
|
feedEntry = FeedEntry()
|
||||||
|
|
||||||
|
# Try to load extensions:
|
||||||
|
for extname,ext in self.__extensions.iteritems():
|
||||||
|
try:
|
||||||
|
feedEntry.load_extension( extname, ext['atom'], ext['rss'] )
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
self.__feed_entries.append( feedEntry )
|
self.__feed_entries.append( feedEntry )
|
||||||
return feedEntry
|
return feedEntry
|
||||||
|
|
||||||
|
@ -942,6 +971,16 @@ class FeedGenerator(object):
|
||||||
entry = [entry]
|
entry = [entry]
|
||||||
if replace:
|
if replace:
|
||||||
self.__feed_entries = []
|
self.__feed_entries = []
|
||||||
|
|
||||||
|
|
||||||
|
# Try to load extensions:
|
||||||
|
for e in entry:
|
||||||
|
for extname,ext in self.__extensions.iteritems():
|
||||||
|
try:
|
||||||
|
e.load_extension( extname, ext['atom'], ext['rss'] )
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
self.__feed_entries += entry
|
self.__feed_entries += entry
|
||||||
return self.__feed_entries
|
return self.__feed_entries
|
||||||
|
|
||||||
|
@ -969,3 +1008,33 @@ class FeedGenerator(object):
|
||||||
remove_entry.
|
remove_entry.
|
||||||
'''
|
'''
|
||||||
self.remove_entry(item)
|
self.remove_entry(item)
|
||||||
|
|
||||||
|
|
||||||
|
def load_extension(self, name, atom=True, rss=True):
|
||||||
|
'''Load a specific extension by name.
|
||||||
|
|
||||||
|
:param name: Name of the extension to load.
|
||||||
|
:param atom: If the extension should be used for ATOM feeds.
|
||||||
|
:param rss: If the extension should be used for RSS feeds.
|
||||||
|
'''
|
||||||
|
# Check loaded extensions
|
||||||
|
if not isinstance(self.__extensions, dict):
|
||||||
|
self.__extensions = {}
|
||||||
|
if name in self.__extensions.keys():
|
||||||
|
raise ImportError('Extension already loaded')
|
||||||
|
|
||||||
|
# Load extension
|
||||||
|
extname = name[0].upper() + name[1:] + 'Extension'
|
||||||
|
supmod = __import__('feedgen.ext.%s' % name)
|
||||||
|
extmod = getattr(supmod.ext, name)
|
||||||
|
ext = getattr(extmod, extname)
|
||||||
|
extinst = ext()
|
||||||
|
setattr(self, name, extinst)
|
||||||
|
self.__extensions[name] = {'inst':extinst,'atom':atom,'rss':rss}
|
||||||
|
|
||||||
|
# Try to load the extension for already existing entries:
|
||||||
|
for entry in self.__feed_entries:
|
||||||
|
try:
|
||||||
|
entry.load_extension( name, atom, rss )
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
0
setup.py
Normal file → Executable file
0
setup.py
Normal file → Executable file
Loading…
Reference in a new issue