diff --git a/PyMediaRSS2Gen.py b/PyMediaRSS2Gen.py
index 0cf7771..6caa0db 100644
--- a/PyMediaRSS2Gen.py
+++ b/PyMediaRSS2Gen.py
@@ -74,9 +74,14 @@ def __init__(
duration=None,
height=None,
width=None,
- lang=None
+ lang=None,
+
+
+ media_thumbnails=None,
):
"""Create a media:content element, args will be attributes."""
+ self.media_thumbnails = media_thumbnails
+
self.element_attrs = OrderedDict()
self._add_attribute('url', url)
@@ -113,7 +118,16 @@ def _add_attribute(self, name, value, allowed_values=None):
def publish(self, handler):
"""Publish the MediaContent as XML."""
- PyRSS2Gen._element(handler, "media:content", None, self.element_attrs)
+ handler.startElement("media:content", self.element_attrs)
+
+ if hasattr(self, 'media_thumbnails'):
+ if not isinstance(self.media_thumbnails, list):
+ self.media_thumbnails = [self.media_thumbnails]
+
+ for t in self.media_thumbnails:
+ PyRSS2Gen._opt_element(handler, "media:thumbnail", t)
+
+ handler.endElement("media:content")
def __repr__(self):
"""Return a nice string representation for prettier debugging."""
@@ -243,3 +257,53 @@ def publish_extensions(self, handler):
if hasattr(self, 'media_text'):
PyRSS2Gen._opt_element(handler, "media:text", self.media_text)
+
+class MediaThumbnail(object):
+
+ """Publish a Media Thumbnail Item."""
+
+ def __init__(
+ self,
+ url,
+ height=None,
+ width=None,
+ time=None # string in the NTP format - see http://www.rssboard.org/media-rss
+ ):
+ """Create a thumbnail element that contains args as attributes."""
+
+ self.element_attrs = OrderedDict()
+ self._add_attribute('url', url)
+ self._add_attribute('width', width)
+ self._add_attribute('height', height)
+ self._add_attribute('time', time)
+
+ self.check_complicance()
+
+ def _add_attribute(self, name, value):
+ """Add an attribute to the MediaContent element."""
+ if value:
+ if isinstance(value, (int, bool)):
+ value = str(value)
+
+ self.element_attrs[name] = value
+
+ def check_complicance(self):
+ """Check compliance with Media RSS Specification, Version 1.5.1.
+
+ see http://www.rssboard.org/media-rss
+ Raises AttributeError on error.
+ """
+
+ if not self.element_attrs.get('url'):
+ raise AttributeError('thumbnail url must be specified')
+
+ if self.element_attrs.get('time'):
+ try:
+ parts = self.element_attrs['time'].split(':')
+ assert len(parts) == 3
+ except AssertionError:
+ raise AttributeError('time, if present, must be in the NTP format')
+
+ def publish(self, handler):
+ """Publish the MediaThumbnail as XML."""
+ PyRSS2Gen._element(handler, "media:thumbnail", None, self.element_attrs)
\ No newline at end of file
diff --git a/tests/fixtures.py b/tests/fixtures.py
new file mode 100644
index 0000000..b061eb0
--- /dev/null
+++ b/tests/fixtures.py
@@ -0,0 +1,17 @@
+# coding=utf-8
+
+""" fixtures """
+
+import pytest
+import PyMediaRSS2Gen as mrss
+
+FEED_URL = 'http://nowhere.org/rss.xml'
+
+@pytest.fixture
+def feed():
+ """ fixture creating an empty feed """
+ return mrss.MediaRSS2(
+ title = 'Test Feed',
+ link = 'http://nowhere.org/nopost',
+ description = 'A testing feed'
+ )
\ No newline at end of file
diff --git a/tests/test_content.py b/tests/test_content.py
new file mode 100644
index 0000000..6288ccc
--- /dev/null
+++ b/tests/test_content.py
@@ -0,0 +1,31 @@
+# coding=utf-8
+
+"""
+tests of MediaContent
+"""
+
+import pytest
+import PyMediaRSS2Gen as mrss
+
+from fixtures import *
+
+class TestMediaContent(object):
+
+ def test_output(self, feed):
+ """ output of a basic content should look like this """
+
+ image = mrss.MediaContent(
+ type='image',
+ url='http://nowhere.org/img/hippo.jpg',
+ )
+ item = mrss.MediaRSSItem(
+ title="Item with thumbnail",
+ media_content=image
+ )
+ feed.items = [item]
+ output = feed.to_xml()
+
+ assert output.endswith(
+ ''+
+ ''
+ )
\ No newline at end of file
diff --git a/tests/test_mediarss2.py b/tests/test_mediarss2.py
new file mode 100644
index 0000000..34461fd
--- /dev/null
+++ b/tests/test_mediarss2.py
@@ -0,0 +1,43 @@
+# coding=utf-8
+
+"""
+tests of the main class -
+MediaRSS2
+"""
+
+import pytest
+import PyMediaRSS2Gen as mrss
+
+from fixtures import *
+
+class Test_EmptyFeed(object):
+
+ def test_toXML(self, feed):
+ """ it is possible to render an empty feed """
+ output = feed.to_xml()
+ assert output.startswith('' in output
+ assert '- ' not in output
+
+ @pytest.mark.xfail(reason='PyRSS2Gen ignores the attribute')
+ def test_hasNamespace(self, feed):
+ """ the feed defines the media module namespace """
+ output = feed.to_xml()
+ assert 'xmlns:media="http://search.yahoo.com/mrss/"' in output
+
+class Test_Items(object):
+
+ def test_noMedia(self, feed):
+ """
+ it is possible to have an item without media content
+ in a media-enabled feed
+
+ The test simply shouldn't throw an error
+ """
+ feed.items = [
+ mrss.MediaRSSItem(
+ title="Item without media content",
+ description="It has no media content",
+ )
+ ]
+ output = feed.to_xml()
diff --git a/tests/test_thumbnail.py b/tests/test_thumbnail.py
new file mode 100644
index 0000000..432d148
--- /dev/null
+++ b/tests/test_thumbnail.py
@@ -0,0 +1,67 @@
+# coding=utf-8
+
+"""
+tests of MediaThumbnail
+"""
+
+import pytest
+import PyMediaRSS2Gen as mrss
+
+from fixtures import *
+
+@pytest.fixture
+def itemWithThumbnail():
+ """ fixture creating an item with thumbnail """
+ thumb = mrss.MediaThumbnail(
+ url='http://nowhere.org/img/hippo_tn.jpg',
+ time='00:15:46',
+ width=150,
+ height=652
+ )
+ image = mrss.MediaContent(
+ type='image',
+ url='http://nowhere.org/img/hippo.jpg',
+ media_thumbnails=thumb
+ )
+ return mrss.MediaRSSItem(
+ title="Item with thumbnail",
+ media_content=image
+ )
+
+class TestMediaThumbnail(object):
+
+ def test_withoutUrl(self):
+ """ url is required """
+ with pytest.raises(AttributeError):
+ mrss.MediaThumbnail(url=None)
+
+ def test_withoutTime(self):
+ """ is ok """
+ mrss.MediaThumbnail(url=FEED_URL)
+
+ def test_withInvalidTime(self):
+ """ time must be in the NTP format """
+ with pytest.raises(AttributeError):
+ mrss.MediaThumbnail(url=FEED_URL, time='notime')
+
+ def test_withValidTime(self):
+ """ is ok """
+ mrss.MediaThumbnail(url=FEED_URL, time='00:05:10')
+ mrss.MediaThumbnail(url=FEED_URL, time='00:05:10.5')
+
+ def test_XMLOutputContainsThumbnail(self, feed, itemWithThumbnail):
+ """ first output test: the thumbnail element must be in the output """
+ feed.items = [itemWithThumbnail]
+ output = feed.to_xml()
+ assert '' +
+ '' +
+ '
'
+ )
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 0000000..59a9cd1
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,9 @@
+[tox]
+envlist=py26,py27,py34
+
+[testenv]
+deps=
+ pytest
+ PyRSS2Gen
+
+commands=py.test
\ No newline at end of file