Commit 213c4b3f authored by Tim Heap's avatar Tim Heap Committed by GitHub
Browse files

Merge pull request #1 from takeflight/autotests

Added travis and tox configs, python2 compatibility, made Video.duration a DurationField.
parents 9b5b8662 69f5b131
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-07-08 06:48 # Generated by Django 1.9.7 on 2016-07-08 06:48
from __future__ import unicode_literals from __future__ import absolute_import, print_function, unicode_literals
from django.db import migrations, models from django.db import migrations, models
......
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-07-28 05:23
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('wagtailvideos', '0007_video_duration'),
]
operations = [
migrations.AlterField(
model_name='video',
name='duration',
field=models.DurationField(blank=True, null=True),
),
]
from __future__ import unicode_literals from __future__ import absolute_import, print_function, unicode_literals
import datetime
import logging
import os import os
import os.path import os.path
import re import re
...@@ -26,6 +28,8 @@ from wagtail.wagtailcore.models import CollectionMember ...@@ -26,6 +28,8 @@ from wagtail.wagtailcore.models import CollectionMember
from wagtail.wagtailsearch import index from wagtail.wagtailsearch import index
from wagtail.wagtailsearch.queryset import SearchableQuerySetMixin from wagtail.wagtailsearch.queryset import SearchableQuerySetMixin
logger = logging.getLogger(__name__)
class MediaFormats(ChoiceEnum): class MediaFormats(ChoiceEnum):
webm = 'VP8 and Vorbis in WebM' webm = 'VP8 and Vorbis in WebM'
...@@ -49,7 +53,7 @@ class AbstractVideo(CollectionMember, TagSearchable): ...@@ -49,7 +53,7 @@ class AbstractVideo(CollectionMember, TagSearchable):
verbose_name=_('file'), upload_to=get_upload_to) verbose_name=_('file'), upload_to=get_upload_to)
thumbnail = models.ImageField(upload_to=get_upload_to, null=True, blank=True) thumbnail = models.ImageField(upload_to=get_upload_to, null=True, blank=True)
created_at = models.DateTimeField(verbose_name=_('created at'), auto_now_add=True, db_index=True) created_at = models.DateTimeField(verbose_name=_('created at'), auto_now_add=True, db_index=True)
duration = models.CharField(max_length=255, blank=True) duration = models.DurationField(blank=True, null=True)
uploaded_by_user = models.ForeignKey( uploaded_by_user = models.ForeignKey(
settings.AUTH_USER_MODEL, verbose_name=_('uploaded by user'), settings.AUTH_USER_MODEL, verbose_name=_('uploaded by user'),
null=True, blank=True, editable=False, on_delete=models.SET_NULL null=True, blank=True, editable=False, on_delete=models.SET_NULL
...@@ -61,6 +65,10 @@ class AbstractVideo(CollectionMember, TagSearchable): ...@@ -61,6 +65,10 @@ class AbstractVideo(CollectionMember, TagSearchable):
objects = VideoQuerySet.as_manager() objects = VideoQuerySet.as_manager()
search_fields = list(TagSearchable.search_fields) + list(CollectionMember.search_fields) + [
index.FilterField('uploaded_by_user'),
]
def is_stored_locally(self): def is_stored_locally(self):
""" """
Returns True if the image is hosted on the local filesystem Returns True if the image is hosted on the local filesystem
...@@ -86,9 +94,6 @@ class AbstractVideo(CollectionMember, TagSearchable): ...@@ -86,9 +94,6 @@ class AbstractVideo(CollectionMember, TagSearchable):
def get_upload_to(self, filename): def get_upload_to(self, filename):
folder_name = 'original_videos' folder_name = 'original_videos'
filename = self.file.field.storage.get_valid_name(filename) filename = self.file.field.storage.get_valid_name(filename)
# do a unidecode in the filename and then
# replace non-ascii characters in filename with _ , to sidestep issues with filesystem encoding
filename = "".join((i if ord(i) < 128 else '_') for i in unidecode(filename))
# Truncate filename so it fits in the 100 character limit # Truncate filename so it fits in the 100 character limit
# https://code.djangoproject.com/ticket/9893 # https://code.djangoproject.com/ticket/9893
...@@ -104,9 +109,13 @@ class AbstractVideo(CollectionMember, TagSearchable): ...@@ -104,9 +109,13 @@ class AbstractVideo(CollectionMember, TagSearchable):
def usage_url(self): def usage_url(self):
return reverse('wagtailvideos:video_usage', args=(self.id,)) return reverse('wagtailvideos:video_usage', args=(self.id,))
search_fields = list(TagSearchable.search_fields) + list(CollectionMember.search_fields) + [ @property
index.FilterField('uploaded_by_user'), def formatted_duration(self):
] if(self.duration):
hours, remainder = divmod(self.duration.seconds, 3600)
minutes, seconds = divmod(remainder, 60)
return "%d:%02d:%02d" % (hours, minutes, seconds)
return ''
def __str__(self): def __str__(self):
return self.title return self.title
...@@ -117,15 +126,15 @@ class AbstractVideo(CollectionMember, TagSearchable): ...@@ -117,15 +126,15 @@ class AbstractVideo(CollectionMember, TagSearchable):
file_path = self.file.path file_path = self.file.path
try: try:
show_format = subprocess.check_output(['ffprobe', '-i', file_path, '-show_format', '-v', 'quiet']) # FIXME prints out extra stuff on travis, pip stderr to dev/null
show_format = subprocess.check_output(['ffprobe', file_path, '-show_format', '-v', 'quiet'])
show_format = show_format.decode("utf-8") show_format = show_format.decode("utf-8")
# show_format comes out in key=value pairs seperated by newlines # show_format comes out in key=value pairs seperated by newlines
duration = re.findall(r'([duration^=]+)=([^=]+)(?:\n|$)', show_format)[0][1] duration = re.findall(r'([duration^=]+)=([^=]+)(?:\n|$)', show_format)[0][1]
hours, remainder = divmod(float(duration), 3600) return datetime.timedelta(seconds=float(duration))
minutes, seconds = divmod(remainder, 60)
return "%d:%02d:%02d" % (hours, minutes, seconds)
except subprocess.CalledProcessError: except subprocess.CalledProcessError:
return '' logger.exception("Getting video duration failed")
return None
def get_thumbnail(self): def get_thumbnail(self):
if self.thumbnail: if self.thumbnail:
......
from __future__ import absolute_import, print_function, unicode_literals
from wagtail.wagtailcore.permission_policies.collections import \ from wagtail.wagtailcore.permission_policies.collections import \
CollectionOwnershipPermissionPolicy CollectionOwnershipPermissionPolicy
from wagtailvideos.models import Video from wagtailvideos.models import Video
permission_policy = CollectionOwnershipPermissionPolicy( permission_policy = CollectionOwnershipPermissionPolicy(
......
...@@ -88,7 +88,7 @@ ...@@ -88,7 +88,7 @@
<dt>{% trans "Filesize" %}</dt> <dt>{% trans "Filesize" %}</dt>
<dd>{% if filesize %}{{ filesize|filesizeformat }}{% else %}{% trans "File not found" %}{% endif %}</dd> <dd>{% if filesize %}{{ filesize|filesizeformat }}{% else %}{% trans "File not found" %}{% endif %}</dd>
<dt>{% trans "Duration" %}</dt> <dt>{% trans "Duration" %}</dt>
<dd>{{ video.duration }}</dd> <dd>{{ video.formatted_duration }}</dd>
</dl> </dl>
</div> </div>
</div> </div>
......
from __future__ import absolute_import, unicode_literals from __future__ import absolute_import, print_function, unicode_literals
from django import template from django import template
from django.forms.widgets import flatatt from django.forms.widgets import flatatt
from django.template import resolve_variable from django.template import resolve_variable
from django.utils.text import mark_safe from django.utils.text import mark_safe
from wagtailvideos.models import MediaFormats, Video from wagtailvideos.models import MediaFormats, Video
register = template.Library() register = template.Library()
......
from __future__ import absolute_import, print_function, unicode_literals
from django.conf.urls import url from django.conf.urls import url
from wagtailvideos.views import chooser, multiple, videos from wagtailvideos.views import chooser, multiple, videos
urlpatterns = [ urlpatterns = [
......
from __future__ import absolute_import, print_function, unicode_literals
try: try:
from shutil import which from shutil import which
except ImportError: except ImportError:
......
from __future__ import absolute_import, print_function, unicode_literals
import json import json
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
...@@ -9,6 +11,7 @@ from wagtail.wagtailadmin.utils import PermissionPolicyChecker ...@@ -9,6 +11,7 @@ from wagtail.wagtailadmin.utils import PermissionPolicyChecker
from wagtail.wagtailcore.models import Collection from wagtail.wagtailcore.models import Collection
from wagtail.wagtailsearch import index as search_index from wagtail.wagtailsearch import index as search_index
from wagtail.wagtailsearch.backends import get_search_backends from wagtail.wagtailsearch.backends import get_search_backends
from wagtailvideos.forms import get_video_form from wagtailvideos.forms import get_video_form
from wagtailvideos.models import Video from wagtailvideos.models import Video
from wagtailvideos.permissions import permission_policy from wagtailvideos.permissions import permission_policy
...@@ -114,6 +117,11 @@ def chooser_upload(request): ...@@ -114,6 +117,11 @@ def chooser_upload(request):
video.save() video.save()
# Reindex the video to make sure all tags are indexed # Reindex the video to make sure all tags are indexed
from wagtail.wagtailcore import __version__
if __version__.startswith("1.4"):
for backend in get_search_backends():
backend.add(video)
else:
search_index.insert_or_update_object(video) search_index.insert_or_update_object(video)
return render_modal_workflow( return render_modal_workflow(
......
from __future__ import absolute_import, print_function, unicode_literals
from django.http import HttpResponseBadRequest, JsonResponse from django.http import HttpResponseBadRequest, JsonResponse
from django.shortcuts import get_object_or_404, render from django.shortcuts import get_object_or_404, render
from django.template.loader import render_to_string from django.template.loader import render_to_string
...@@ -6,6 +8,7 @@ from django.views.decorators.http import require_POST ...@@ -6,6 +8,7 @@ from django.views.decorators.http import require_POST
from django.views.decorators.vary import vary_on_headers from django.views.decorators.vary import vary_on_headers
from wagtail.wagtailadmin.utils import PermissionPolicyChecker from wagtail.wagtailadmin.utils import PermissionPolicyChecker
from wagtail.wagtailsearch.backends import get_search_backends from wagtail.wagtailsearch.backends import get_search_backends
from wagtailvideos.forms import get_video_form from wagtailvideos.forms import get_video_form
from wagtailvideos.models import Video from wagtailvideos.models import Video
from wagtailvideos.permissions import permission_policy from wagtailvideos.permissions import permission_policy
......
from __future__ import absolute_import, print_function, unicode_literals
import os import os
from django.core.urlresolvers import NoReverseMatch, reverse from django.core.urlresolvers import NoReverseMatch, reverse
...@@ -11,6 +13,7 @@ from wagtail.wagtailadmin.forms import SearchForm ...@@ -11,6 +13,7 @@ from wagtail.wagtailadmin.forms import SearchForm
from wagtail.wagtailadmin.utils import PermissionPolicyChecker from wagtail.wagtailadmin.utils import PermissionPolicyChecker
from wagtail.wagtailcore.models import Collection, Site from wagtail.wagtailcore.models import Collection, Site
from wagtail.wagtailsearch.backends import get_search_backends from wagtail.wagtailsearch.backends import get_search_backends
from wagtailvideos.forms import VideoTranscodeAdminForm, get_video_form from wagtailvideos.forms import VideoTranscodeAdminForm, get_video_form
from wagtailvideos.models import Video from wagtailvideos.models import Video
from wagtailvideos.permissions import permission_policy from wagtailvideos.permissions import permission_policy
...@@ -125,7 +128,7 @@ def create_transcode(request, video_id): ...@@ -125,7 +128,7 @@ def create_transcode(request, video_id):
return HttpResponseNotAllowed(['POST']) return HttpResponseNotAllowed(['POST'])
video = get_object_or_404(Video, id=video_id) video = get_object_or_404(Video, id=video_id)
transcode_form = VideoTranscodeAdminForm(request.POST, video=video) transcode_form = VideoTranscodeAdminForm(data=request.POST, video=video)
if transcode_form.is_valid(): if transcode_form.is_valid():
transcode_form.save() transcode_form.save()
......
from __future__ import unicode_literals from __future__ import absolute_import, print_function, unicode_literals
from django.conf.urls import include, url from django.conf.urls import include, url
from django.contrib.staticfiles.templatetags.staticfiles import static from django.contrib.staticfiles.templatetags.staticfiles import static
...@@ -7,6 +7,7 @@ from django.utils.html import format_html, format_html_join ...@@ -7,6 +7,7 @@ from django.utils.html import format_html, format_html_join
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from wagtail.wagtailadmin.menu import MenuItem from wagtail.wagtailadmin.menu import MenuItem
from wagtail.wagtailcore import hooks from wagtail.wagtailcore import hooks
from wagtailvideos.forms import GroupVideoPermissionFormSet from wagtailvideos.forms import GroupVideoPermissionFormSet
from . import urls from . import urls
......
from __future__ import absolute_import, unicode_literals from __future__ import absolute_import, print_function, unicode_literals
import json import json
from django.template.loader import render_to_string from django.template.loader import render_to_string
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from wagtail.wagtailadmin.widgets import AdminChooser from wagtail.wagtailadmin.widgets import AdminChooser
from wagtailvideos.models import Video from wagtailvideos.models import Video
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment