diff --git a/.travis.yml b/.travis.yml
index acfb872..e6e2844 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,14 +3,30 @@ language: python
python:
- "2.7"
- "3.4"
+ - "3.6"
cache: pip
env:
- - DJANGO_VERSION=1.5.2
- - DJANGO_VERSION=1.6.5
- - DJANGO_VERSION=1.7.0
- - DJANGO_VERSION=1.8.0
- - DJANGO_VERSION=1.8.6
- - DJANGO_VERSION=1.9.4
+ - DJANGO_VERSION=1.5.*
+ - DJANGO_VERSION=1.6.*
+ - DJANGO_VERSION=1.7.*
+ - DJANGO_VERSION=1.8.*
+ - DJANGO_VERSION=1.9.*
+ - DJANGO_VERSION=1.10.*
+ - DJANGO_VERSION=1.11.*
+matrix:
+ exclude:
+ - python: '3.6'
+ env: DJANGO_VERSION=1.5.*
+ - python: '3.6'
+ env: DJANGO_VERSION=1.6.*
+ - python: '3.6'
+ env: DJANGO_VERSION=1.7.*
+ - python: '3.6'
+ env: DJANGO_VERSION=1.8.*
+ - python: '3.6'
+ env: DJANGO_VERSION=1.9.*
+ - python: '3.6'
+ env: DJANGO_VERSION=1.10.*
install:
- pip install -q Django==$DJANGO_VERSION
- pip install coveralls
diff --git a/README.rst b/README.rst
index d5c763d..5c56e54 100644
--- a/README.rst
+++ b/README.rst
@@ -37,14 +37,22 @@ Quick start
#. Add ``embed_video`` to ``INSTALLED_APPS`` in your Django settings.
#. If you want to detect HTTP/S in template tags, you have to set ``request``
- context processor in ``settings.TEMPLATE_CONTEXT_PROCESSORS``:
+ context processor in ``settings.TEMPLATES``:
::
- TEMPLATE_CONTEXT_PROCESSORS = (
- ...
- 'django.core.context_processors.request',
- )
+ TEMPLATES = [
+ {
+ 'BACKEND': 'django.template.backends.django.DjangoTemplates',
+ # ...
+ 'OPTIONS': {
+ 'context_processors': [
+ # ...
+ 'django.template.context_processors.request',
+ ],
+ },
+ },
+ ]
#. Usage of template tags:
diff --git a/embed_video/tests/django_settings.py b/embed_video/tests/django_settings.py
index a1c8acf..3a394f2 100644
--- a/embed_video/tests/django_settings.py
+++ b/embed_video/tests/django_settings.py
@@ -1,13 +1,29 @@
import os
-from django.conf.global_settings import *
-
DEBUG = True
SECRET_KEY = 'testing_key123'
STATIC_ROOT = MEDIA_ROOT = os.path.join(os.path.dirname(__file__), 'static')
STATIC_URL = MEDIA_URL = '/static/'
+TEMPLATES = [
+ {
+ 'BACKEND': 'django.template.backends.django.DjangoTemplates',
+ 'APP_DIRS': True,
+ 'OPTIONS': {
+ 'context_processors': [
+ 'django.contrib.auth.context_processors.auth',
+ 'django.template.context_processors.debug',
+ 'django.template.context_processors.i18n',
+ 'django.template.context_processors.media',
+ 'django.template.context_processors.static',
+ 'django.template.context_processors.tz',
+ 'django.contrib.messages.context_processors.messages',
+ ],
+ },
+ },
+]
+
INSTALLED_APPS = (
'django.contrib.contenttypes',
'django.contrib.auth',
diff --git a/embed_video/tests/templatetags/tests_embed_video_tags.py b/embed_video/tests/templatetags/tests_embed_video_tags.py
index c66c3db..f571bfc 100644
--- a/embed_video/tests/templatetags/tests_embed_video_tags.py
+++ b/embed_video/tests/templatetags/tests_embed_video_tags.py
@@ -1,9 +1,15 @@
from unittest import TestCase, skip
from mock import Mock, patch
+import sys
import re
+if sys.version_info.major == 3:
+ import urllib.parse as urlparse
+else:
+ import urlparse
+
from django.template import TemplateSyntaxError
-from django.http import HttpRequest
+from django.http import HttpRequest, QueryDict
from django.template.base import Template
from django.template.context import RequestContext
from django.test.client import RequestFactory
@@ -15,10 +21,38 @@ URL_PATTERN = re.compile(r'src="?\'?([^"\'>]*)"')
class EmbedTestCase(TestCase):
- def assertRenderedTemplate(self, template_string, output, context=None):
+ def render_template(self, template_string, context=None):
response = RequestContext(HttpRequest(), context)
- rendered_output = Template(template_string).render(response)
- self.assertEqual(rendered_output.strip(), output.strip())
+ return Template(template_string).render(response).strip()
+
+ def assertRenderedTemplate(self, template_string, output, context=None):
+ rendered_output = self.render_template(template_string, context=context)
+ self.assertEqual(rendered_output, output.strip())
+
+ def url_dict(self, url):
+ """
+ Parse the URL into a format suitable for comparison, ignoring the query
+ parameter order.
+ """
+
+ parsed = urlparse.urlparse(url)
+ query = urlparse.parse_qs(parsed.query)
+
+ return {
+ 'scheme': parsed.scheme,
+ 'netloc': parsed.netloc,
+ 'path': parsed.path,
+ 'params': parsed.params,
+ 'query': query,
+ 'fragment': parsed.fragment,
+ }
+
+ def assertUrlEqual(self, actual, expected, msg=None):
+ """Assert two URLs are equal, ignoring the query parameter order."""
+ actual_dict = self.url_dict(actual)
+ expected_dict = self.url_dict(expected)
+
+ self.assertEqual(actual_dict, expected_dict, msg=msg)
def test_embed(self):
template = """
@@ -195,9 +229,11 @@ class EmbedTestCase(TestCase):
{{ ytb.url }}
{% endvideo %}
"""
- self.assertRenderedTemplate(
- template,
- 'http://www.youtube.com/embed/jsrRJyHBvzw?wmode=transparent&rel=1'
+
+ output = self.render_template(template)
+ self.assertUrlEqual(
+ output,
+ 'http://www.youtube.com/embed/jsrRJyHBvzw?rel=1&wmode=transparent'
)
def test_direct_embed_with_query(self):
@@ -206,10 +242,25 @@ class EmbedTestCase(TestCase):
{% video 'http://www.youtube.com/watch?v=jsrRJyHBvzw' query="rel=1&wmode=transparent" %}
"""
- self.assertRenderedTemplate(
- template,
+ output = self.render_template(template)
+
+ # The order of query parameters in the URL might change between Python
+ # versions. Compare the URL and the outer part separately.
+
+ url_pattern = re.compile(r'http[^"]+')
+ url = url_pattern.search(output).group(0)
+
+ self.assertUrlEqual(
+ url,
+ 'http://www.youtube.com/embed/jsrRJyHBvzw?rel=1&wmode=transparent'
+ )
+
+ output_without_url = url_pattern.sub('URL', output)
+
+ self.assertEqual(
+ output_without_url,
''
)
diff --git a/embed_video/tests/tests_admin.py b/embed_video/tests/tests_admin.py
index 50b2c81..0feda69 100644
--- a/embed_video/tests/tests_admin.py
+++ b/embed_video/tests/tests_admin.py
@@ -1,11 +1,13 @@
from unittest import TestCase
+from django.test import SimpleTestCase
+
from embed_video.admin import AdminVideoWidget, AdminVideoMixin
from embed_video.backends import VimeoBackend
from embed_video.fields import EmbedVideoField, EmbedVideoFormField
-class AdminVideoWidgetTestCase(TestCase):
+class AdminVideoWidgetTestCase(SimpleTestCase):
def test_size(self):
widget = AdminVideoWidget()
self.assertTrue('size' in widget.attrs)
@@ -21,15 +23,15 @@ class AdminVideoWidgetTestCase(TestCase):
def test_render_empty_value(self):
widget = AdminVideoWidget(attrs={'size': '0'})
- self.assertEqual(widget.render('foo'),
- '')
+ self.assertHTMLEqual(widget.render('foo'),
+ '')
def test_render(self):
backend = VimeoBackend('https://vimeo.com/1')
widget = AdminVideoWidget(attrs={'size': '0'})
widget.output_format = '{video}{input}'
- self.assertEqual(
+ self.assertHTMLEqual(
widget.render('foo', backend.url, size=(100, 100)),
backend.get_embed_code(100, 100)
+ ''
@@ -38,14 +40,14 @@ class AdminVideoWidgetTestCase(TestCase):
def test_render_unknown_backend(self):
widget = AdminVideoWidget()
- self.assertEqual(
+ self.assertHTMLEqual(
widget.render('foo', 'abcd'),
''
)
def test_render_video_doesnt_exist(self):
widget = AdminVideoWidget()
- self.assertEqual(
+ self.assertHTMLEqual(
widget.render('foo', 'https://soundcloud.com/xyz/foo'),
''
)
diff --git a/example_project/README.rst b/example_project/README.rst
index 113a29d..604c4c1 100644
--- a/example_project/README.rst
+++ b/example_project/README.rst
@@ -1,13 +1,16 @@
Running example project
***********************
-#. Install Django and PyYAML::
+#. Install requirements::
- pip install Django
- pip install pyyaml
+ pip install -r requirements.txt
#. Create database::
+ python manage.py migrate --run-syncdb --noinput
+
+ Or, for older versions of Django::
+
python manage.py syncdb --noinput
#. Run testing server::
diff --git a/example_project/example_project/settings.py b/example_project/example_project/settings.py
index 7e153ff..a14a08d 100644
--- a/example_project/example_project/settings.py
+++ b/example_project/example_project/settings.py
@@ -1,7 +1,7 @@
# Django settings for example_project project.
+import django
DEBUG = True
-TEMPLATE_DEBUG = DEBUG
DATABASES = {
'default': {
@@ -14,21 +14,45 @@ SITE_ID = 1
SECRET_KEY = 'u%38dln@$1!7w#cxi4np504^sa3_skv5aekad)jy_u0v2mc+nr'
-TEMPLATE_CONTEXT_PROCESSORS = (
- 'django.contrib.auth.context_processors.auth',
- 'django.core.context_processors.debug',
- 'django.core.context_processors.i18n',
- 'django.core.context_processors.media',
- 'django.core.context_processors.static',
- 'django.core.context_processors.tz',
- 'django.contrib.messages.context_processors.messages',
- 'django.core.context_processors.request',
-)
+TEMPLATES = [
+ {
+ 'BACKEND': 'django.template.backends.django.DjangoTemplates',
+ 'APP_DIRS': True,
+ 'OPTIONS': {
+ 'context_processors': [
+ 'django.template.context_processors.debug',
+ 'django.template.context_processors.i18n',
+ 'django.template.context_processors.media',
+ 'django.template.context_processors.static',
+ 'django.template.context_processors.tz',
+ 'django.template.context_processors.request',
+ 'django.contrib.auth.context_processors.auth',
+ 'django.contrib.messages.context_processors.messages',
+ ],
+ },
+ },
+]
-TEMPLATE_LOADERS = (
- 'django.template.loaders.filesystem.Loader',
- 'django.template.loaders.app_directories.Loader',
-)
+if django.VERSION >= (1, 10):
+ MIDDLEWARE = [
+ 'django.middleware.security.SecurityMiddleware',
+ 'django.contrib.sessions.middleware.SessionMiddleware',
+ 'django.middleware.common.CommonMiddleware',
+ 'django.middleware.csrf.CsrfViewMiddleware',
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
+ 'django.contrib.messages.middleware.MessageMiddleware',
+ 'django.middleware.clickjacking.XFrameOptionsMiddleware',
+ ]
+else:
+ MIDDLEWARE_CLASSES = [
+ 'django.middleware.security.SecurityMiddleware',
+ 'django.contrib.sessions.middleware.SessionMiddleware',
+ 'django.middleware.common.CommonMiddleware',
+ 'django.middleware.csrf.CsrfViewMiddleware',
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
+ 'django.contrib.messages.middleware.MessageMiddleware',
+ 'django.middleware.clickjacking.XFrameOptionsMiddleware',
+ ]
APPEND_SLASH = True
diff --git a/example_project/example_project/urls.py b/example_project/example_project/urls.py
index 1b0c32d..cb7110d 100644
--- a/example_project/example_project/urls.py
+++ b/example_project/example_project/urls.py
@@ -1,11 +1,11 @@
-from django.conf.urls import patterns, include, url
+from django.conf.urls import include, url
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.contrib import admin
admin.autodiscover()
urlpatterns = staticfiles_urlpatterns() \
- + patterns('',
+ + [
url(r'^admin/', include(admin.site.urls)),
url(r'^', include('posts.urls', namespace='posts')),
- )
+ ]
diff --git a/example_project/posts/urls.py b/example_project/posts/urls.py
index 122e793..bce5bd8 100644
--- a/example_project/posts/urls.py
+++ b/example_project/posts/urls.py
@@ -1,8 +1,8 @@
-from django.conf.urls import patterns, url
+from django.conf.urls import url
from .views import PostListView, PostDetailView
-urlpatterns = patterns('',
+urlpatterns = [
url(r'(?P\d+)/$', PostDetailView.as_view(), name='detail'),
url(r'$', PostListView.as_view(), name='list'),
-)
+]
diff --git a/example_project/requirements.txt b/example_project/requirements.txt
index be600a3..ef06f9e 100644
--- a/example_project/requirements.txt
+++ b/example_project/requirements.txt
@@ -1 +1,3 @@
Django>=1.5
+pyyaml
+requests