From 08641afae9c5a085caf943a2194b983f1dd1f657 Mon Sep 17 00:00:00 2001 From: Juda Kaleta Date: Tue, 20 Aug 2013 10:49:33 +0200 Subject: [PATCH] Closes #5. Add {{ my_video.backend }} containing YoutubeBackend, VimeoBackend or SoundCloudBackend values. - Fix: SoundClound --> SoundCloud - added tests for template tags --- README.rst | 1 + embed_video/base.py | 67 +++++----- embed_video/templatetags/embed_video_tags.py | 37 ++++-- embed_video/tests/tests_backend.py | 73 +---------- embed_video/tests/tests_fields.py | 6 + embed_video/tests/tests_tags.py | 123 ++++++++++++++++++- 6 files changed, 190 insertions(+), 117 deletions(-) diff --git a/README.rst b/README.rst index 9dc0817..4614e46 100644 --- a/README.rst +++ b/README.rst @@ -65,6 +65,7 @@ Usage of variables: {% video item.video as my_video %} URL: {{ my_video.url }} Thumbnail: {{ my_video.thumbnail }} + Backend: {{ my_video.backend }} {% endvideo %} diff --git a/embed_video/base.py b/embed_video/base.py index 04ab341..002dfb4 100644 --- a/embed_video/base.py +++ b/embed_video/base.py @@ -28,7 +28,7 @@ def detect_backend(url): elif DETECT_VIMEO.match(url): return VimeoBackend(url) elif DETECT_SOUNDCLOUD.match(url): - return SoundCloundBackend(url) + return SoundCloudBackend(url) else: raise UnknownBackendException @@ -37,6 +37,7 @@ class VideoBackend(object): def __init__(self, url): self._url = url + self.backend = self.__class__.__name__ self.code = self.get_code() self.url = self.get_url() self.thumbnail = self.get_thumbnail_url() @@ -53,38 +54,6 @@ class VideoBackend(object): return self.pattern_thumbnail_url % self.code -class SoundCloundBackend(VideoBackend): - base_url = 'http://soundcloud.com/oembed' - - re_code = re.compile(r'src=".*%2F(?P\d+)&show_artwork.*"', re.I) - re_url = re.compile(r'src="(?P.*?)"', re.I) - - def __init__(self, url): - params = { - 'format': 'json', - 'url': url, - } - - r = requests.get(self.base_url, data=params) - self.response = json.loads(r.text) - - self.width = self.response.get('width') - self.height = self.response.get('height') - - super(SoundCloundBackend, self).__init__(url) - - def get_thumbnail_url(self): - return self.response.get('thumbnail_url') - - def get_url(self): - match = self.re_url.search(self.response.get('html')) - return match.group('url') - - def get_code(self): - match = self.re_code.search(self.response.get('html')) - return match.group('code') - - class YoutubeBackend(VideoBackend): re_code = re.compile( r'youtu(?:be\.com/watch\?v=|\.be/)(?P[\w-]*)(&(amp;)?[\w\?=]*)?', @@ -112,3 +81,35 @@ class VimeoBackend(VideoBackend): def get_thumbnail_url(self): pass # not implemented + + +class SoundCloudBackend(VideoBackend): + base_url = 'http://soundcloud.com/oembed' + + re_code = re.compile(r'src=".*%2F(?P\d+)&show_artwork.*"', re.I) + re_url = re.compile(r'src="(?P.*?)"', re.I) + + def __init__(self, url): + params = { + 'format': 'json', + 'url': url, + } + + r = requests.get(self.base_url, data=params) + self.response = json.loads(r.text) + + self.width = self.response.get('width') + self.height = self.response.get('height') + + super(SoundCloudBackend, self).__init__(url) + + def get_thumbnail_url(self): + return self.response.get('thumbnail_url') + + def get_url(self): + match = self.re_url.search(self.response.get('html')) + return match.group('url') + + def get_code(self): + match = self.re_code.search(self.response.get('html')) + return match.group('code') diff --git a/embed_video/templatetags/embed_video_tags.py b/embed_video/templatetags/embed_video_tags.py index 89783ae..4772a25 100644 --- a/embed_video/templatetags/embed_video_tags.py +++ b/embed_video/templatetags/embed_video_tags.py @@ -1,7 +1,7 @@ from django.template import Library, Node, TemplateSyntaxError from django.utils.safestring import mark_safe, SafeText -from ..base import detect_backend, SoundCloundBackend +from ..base import detect_backend, SoundCloudBackend register = Library() @@ -43,6 +43,17 @@ def embed(backend, _size='small'): if isinstance(backend, SafeText): backend = detect_backend(backend) + size = _embed_get_size(_size) + params = _embed_get_params(backend, size) + + return mark_safe( + '' % params + ) + + +def _embed_get_size(size): sizes = { 'tiny': (420, 315), 'small': (480, 360), @@ -51,22 +62,22 @@ def embed(backend, _size='small'): 'huge': (1280, 960), } - if _size in sizes: - size = sizes[_size] - elif 'x' in _size: - size = _size.split('x') + if size in sizes: + return sizes[size] + elif 'x' in size: + return [int(x) for x in size.split('x')] + +def _embed_get_params(backend, size): params = { 'url': backend.url, - 'width': int(size[0]), - 'height': int(size[1]), + 'width': size[0], + 'height': size[1], } - if isinstance(backend, SoundCloundBackend): + if isinstance(backend, SoundCloudBackend): params.update({'height': backend.height}) - return mark_safe( - '' % params - ) + return params + + diff --git a/embed_video/tests/tests_backend.py b/embed_video/tests/tests_backend.py index d13086e..dee5e08 100644 --- a/embed_video/tests/tests_backend.py +++ b/embed_video/tests/tests_backend.py @@ -1,11 +1,7 @@ from unittest import TestCase -from django.http import HttpRequest -from django.template.base import Template -from django.template.context import RequestContext - from ..base import detect_backend, YoutubeBackend, VimeoBackend, \ - SoundCloundBackend, UnknownBackendException + SoundCloudBackend, UnknownBackendException class EmbedVideoTestCase(TestCase): @@ -43,70 +39,9 @@ class EmbedVideoTestCase(TestCase): from django.conf import settings as django_settings self.django_settings = django_settings - def _grc(self): - return RequestContext(HttpRequest()) - - def test_embed(self): - template = Template(""" - {% load embed_video_tags %} - {% video 'http://www.youtube.com/watch?v=jsrRJyHBvzw' as ytb %} - {{ ytb|embed:'large' }} - {% endvideo %} - """) - rendered = u'' - - self.assertEqual(template.render(self._grc()).strip(), rendered) - - def test_direct_embed(self): - template = Template(""" - {% load embed_video_tags %} - {{ 'http://www.youtube.com/watch?v=jsrRJyHBvzw'|embed:'large' }} - """) - rendered = u'' - - self.assertEqual(template.render(self._grc()).strip(), rendered) - - def test_embed_user_size(self): - template = Template(""" - {% load embed_video_tags %} - {% video 'http://www.youtube.com/watch?v=jsrRJyHBvzw' as ytb %} - {{ ytb|embed:'800x800' }} - {% endvideo %} - """) - rendered = u'' - - self.assertEqual(template.render(self._grc()).strip(), rendered) - - def test_tag_youtube(self): - template = Template(""" - {% load embed_video_tags %} - {% video 'http://www.youtube.com/watch?v=jsrRJyHBvzw' as ytb %} - {{ ytb.url }} - {% endvideo %} - """) - rendered = 'http://www.youtube.com/embed/jsrRJyHBvzw?wmode=opaque' - - self.assertEqual(template.render(self._grc()).strip(), rendered) - - def test_tag_vimeo(self): - template = Template(""" - {% load embed_video_tags %} - {% video 'https://vimeo.com/66577491' as vimeo %} - {{ vimeo.url }} - {% endvideo %} - """) - rendered = 'http://player.vimeo.com/video/66577491' - - self.assertEqual(template.render(self._grc()).strip(), rendered) - def test_detect_bad_urls(self): for url in self.unknown_backend_urls: - try: - backend = detect_backend(url) - self.assertEqual(backend, False) - except UnknownBackendException: - assert True - + self.assertRaises(UnknownBackendException, detect_backend, url) def test_detect_youtube(self): for url in self.youtube_urls: @@ -121,7 +56,7 @@ class EmbedVideoTestCase(TestCase): def test_detect_soundcloud(self): for url in self.soundcloud_urls: backend = detect_backend(url[0]) - self.assertIsInstance(backend, SoundCloundBackend) + self.assertIsInstance(backend, SoundCloudBackend) def test_code_youtube(self): for url in self.youtube_urls: @@ -137,6 +72,6 @@ class EmbedVideoTestCase(TestCase): def test_code_soundcloud(self): for url in self.soundcloud_urls: - backend = SoundCloundBackend(url[0]) + backend = SoundCloudBackend(url[0]) code = backend.get_code() self.assertEqual(code, url[1]) diff --git a/embed_video/tests/tests_fields.py b/embed_video/tests/tests_fields.py index 8f98084..e392977 100644 --- a/embed_video/tests/tests_fields.py +++ b/embed_video/tests/tests_fields.py @@ -39,3 +39,9 @@ class EmbedVideoFormFieldTestCase(TestCase): mock_detect_backend.side_effect = UnknownIdException self.assertRaises(ValidationError, self.formfield.validate, ('http://youtube.com/v/123/',)) + + def test_validation_correct(self): + url = 'http://my-testing.url.com' + with patch('embed_video.fields.detect_backend') as mock_detect_backend: + mock_detect_backend.return_value = True + self.assertEqual(url, self.formfield.validate(url)) diff --git a/embed_video/tests/tests_tags.py b/embed_video/tests/tests_tags.py index 5b02cc8..9bd365c 100644 --- a/embed_video/tests/tests_tags.py +++ b/embed_video/tests/tests_tags.py @@ -2,8 +2,13 @@ from unittest import TestCase from mock import Mock from django.template import TemplateSyntaxError +from django.http import HttpRequest +from django.template.base import Template +from django.template.context import RequestContext -from ..templatetags.embed_video_tags import VideoNode +from embed_video.base import YoutubeBackend, SoundCloudBackend +from embed_video.templatetags.embed_video_tags import VideoNode, \ + _embed_get_size, _embed_get_params class EmbedVideoNodeTestCase(TestCase): @@ -11,11 +16,97 @@ class EmbedVideoNodeTestCase(TestCase): self.parser = Mock() self.token = Mock(methods=['split_contents']) + def _grc(self): + return RequestContext(HttpRequest()) + + def test_embed(self): + template = Template(""" + {% load embed_video_tags %} + {% video 'http://www.youtube.com/watch?v=jsrRJyHBvzw' as ytb %} + {{ ytb|embed:'large' }} + {% endvideo %} + """) + rendered = u'' + + self.assertEqual(template.render(self._grc()).strip(), rendered) + + def test_direct_embed(self): + template = Template(""" + {% load embed_video_tags %} + {{ 'http://www.youtube.com/watch?v=jsrRJyHBvzw'|embed:'large' }} + """) + rendered = u'' + + self.assertEqual(template.render(self._grc()).strip(), rendered) + + def test_embed_user_size(self): + template = Template(""" + {% load embed_video_tags %} + {% video 'http://www.youtube.com/watch?v=jsrRJyHBvzw' as ytb %} + {{ ytb|embed:'800x800' }} + {% endvideo %} + """) + rendered = u'' + + self.assertEqual(template.render(self._grc()).strip(), rendered) + + def test_tag_youtube(self): + template = Template(""" + {% load embed_video_tags %} + {% video 'http://www.youtube.com/watch?v=jsrRJyHBvzw' as ytb %} + {{ ytb.url }} + {% endvideo %} + """) + rendered = 'http://www.youtube.com/embed/jsrRJyHBvzw?wmode=opaque' + + self.assertEqual(template.render(self._grc()).strip(), rendered) + + def test_tag_vimeo(self): + template = Template(""" + {% load embed_video_tags %} + {% video 'https://vimeo.com/66577491' as vimeo %} + {{ vimeo.url }} + {% endvideo %} + """) + rendered = 'http://player.vimeo.com/video/66577491' + + self.assertEqual(template.render(self._grc()).strip(), rendered) + + def test_tag_backend_variable_vimeo(self): + template = Template(""" + {% load embed_video_tags %} + {% video 'https://vimeo.com/66577491' as vimeo %} + {{ vimeo.backend }} + {% endvideo %} + """) + rendered = 'VimeoBackend' + self.assertEqual(template.render(self._grc()).strip(), rendered) + + def test_tag_backend_variable_youtube(self): + template = Template(""" + {% load embed_video_tags %} + {% video 'http://www.youtube.com/watch?v=jsrRJyHBvz' as youtube %} + {{ youtube.backend }} + {% endvideo %} + """) + rendered = 'YoutubeBackend' + self.assertEqual(template.render(self._grc()).strip(), rendered) + + def test_tag_backend_variable_soundcloud(self): + template = Template(""" + {% load embed_video_tags %} + {% video 'https://soundcloud.com/glassnote/mumford-sons-i-will-wait' as soundcloud %} + {{ soundcloud.backend }} + {% endvideo %} + """) + rendered = 'SoundCloudBackend' + self.assertEqual(template.render(self._grc()).strip(), rendered) + def test_syntax_error(self): self.token.split_contents.return_value = [] try: - instance = VideoNode(self.parser, self.token) + VideoNode(self.parser, self.token) except TemplateSyntaxError: assert True @@ -28,4 +119,32 @@ class EmbedVideoNodeTestCase(TestCase): node = VideoNode(self.parser, self.token) self.assertEqual(str(node), '') + def test_embed_get_params(self): + url = 'http://youtu.be/13456' + backend = YoutubeBackend(url) + params = _embed_get_params(backend, (3, 8)) + + self.assertEqual('http://www.youtube.com/embed/13456?wmode=opaque', params['url']) + self.assertEqual(3, params['width']) + self.assertEqual(8, params['height']) + + def test_embed_get_params_soundcloud_height(self): + url = 'https://soundcloud.com/glassnote/mumford-sons-i-will-wait' + backend = SoundCloudBackend(url) + params = _embed_get_params(backend, (1, 2)) + + self.assertEqual(backend.height, params['height']) + + def test_videonode_iter(self): + out = ['a', 'b', 'c', 'd'] + + class FooNode(VideoNode): + nodelist_file = out + + def __init__(self): + pass + + node = FooNode() + self.assertEqual(out, [x for x in node]) +