diff --git a/pod/dressing/admin.py b/pod/dressing/admin.py index b7a803c200..c39da3df0f 100644 --- a/pod/dressing/admin.py +++ b/pod/dressing/admin.py @@ -4,6 +4,7 @@ class DressingAdmin(admin.ModelAdmin): + """Dressing admin page.""" form = DressingForm list_display = ("title", "watermark", "opacity", "position", "opening_credits", "ending_credits") diff --git a/pod/dressing/forms.py b/pod/dressing/forms.py index ab564902a6..924164190f 100644 --- a/pod/dressing/forms.py +++ b/pod/dressing/forms.py @@ -44,12 +44,14 @@ class AddVideoHoldWidget(s2forms.ModelSelect2Widget): class DressingForm(forms.ModelForm): + """Form to add or edit a dressing.""" is_staff = True is_superuser = False admin_form = True site = forms.ModelChoiceField(Site.objects.all(), required=False) def __init__(self, *args, **kwargs): + """Init method.""" self.is_staff = ( kwargs.pop("is_staff") if "is_staff" in kwargs.keys() else self.is_staff ) @@ -91,6 +93,7 @@ def __init__(self, *args, **kwargs): self.fields["ending_credits"].queryset = query_videos.all() class Meta(object): + """Meta class.""" model = Dressing fields = "__all__" exclude = ['videos'] @@ -104,6 +107,7 @@ class Meta(object): class DressingDeleteForm(forms.Form): + """Form to delete a dressing.""" agree = forms.BooleanField( label=_("I agree"), help_text=_("Delete dressing cannot be undo"), diff --git a/pod/dressing/models.py b/pod/dressing/models.py index c97c22305e..059acf9ae1 100644 --- a/pod/dressing/models.py +++ b/pod/dressing/models.py @@ -104,10 +104,12 @@ class Dressing(models.Model): ) class Meta: + """Metadata for Dressing model.""" verbose_name = _("Video dressing") verbose_name_plural = _("Video dressings") def to_json(self): + """Convert to json format for encoding logs""" return { "id": self.id, "title": self.title, diff --git a/pod/dressing/test.py b/pod/dressing/test.py deleted file mode 100644 index 7ce503c2dd..0000000000 --- a/pod/dressing/test.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.test import TestCase - -# Create your tests here. diff --git a/pod/dressing/tests/__init__.py b/pod/dressing/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/pod/dressing/tests/test_models.py b/pod/dressing/tests/test_models.py new file mode 100644 index 0000000000..88827d34da --- /dev/null +++ b/pod/dressing/tests/test_models.py @@ -0,0 +1,104 @@ +"""Unit tests for dressing models.""" + +import os +from django.test import TestCase +from django.contrib.auth.models import User +from django.conf import settings +from django.core.files.uploadedfile import SimpleUploadedFile +from pod.video.models import Type, Video +from pod.dressing.models import Dressing + +if getattr(settings, "USE_PODFILE", False): + from pod.podfile.models import CustomImageModel + from pod.podfile.models import UserFolder + + FILEPICKER = True +else: + FILEPICKER = False + from pod.main.models import CustomImageModel + + +class DressingModelTest(TestCase): + """Test case for Pod dressing models.""" + def setUp(self): + owner = User.objects.create(username="pod") + currentdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + simplefile = SimpleUploadedFile( + name="testimage.jpg", + content=open(os.path.join(currentdir, "tests", "testimage.jpg"), "rb").read(), + content_type="image/jpeg", + ) + + home = UserFolder.objects.get(name="home", owner=owner) + if FILEPICKER: + home = UserFolder.objects.get(name="home", owner=owner) + customImage = CustomImageModel.objects.create( + name="testimage", + description="testimage", + created_by=owner, + folder=home, + file=simplefile, + ) + else: + customImage = CustomImageModel.objects.create(file=simplefile) + videotype = Type.objects.create(title="others") + video = Video.objects.create( + title="video", + type=videotype, + owner=owner, + video="test.mp4", + duration=20, + ) + video2 = Video.objects.create( + title="video2", + type=videotype, + owner=owner, + video="test2.mp4", + duration=20, + ) + dressing = Dressing.objects.create( + title='Test Dressing', + watermark=customImage, + position=Dressing.TOP_RIGHT, + opacity=50, + opening_credits=video, + ending_credits=video2, + ) + dressing.owners.set([owner]) + dressing.users.set([owner]) + + def test_attributs_full(self): + dressing = Dressing.objects.get(id=1) + owner = User.objects.get(username="pod") + video = Video.objects.get(id=1) + video2 = Video.objects.get(id=2) + self.assertEqual(dressing.title, 'Test Dressing') + self.assertEqual(list(dressing.owners.all()), [owner]) + self.assertEqual(list(dressing.users.all()), [owner]) + self.assertEqual(list(dressing.allow_to_groups.all()), []) + self.assertTrue("testimage" in dressing.watermark.name) + self.assertEqual(dressing.position, Dressing.TOP_RIGHT) + self.assertEqual(dressing.opacity, 50) + self.assertEqual(dressing.opening_credits, video) + self.assertEqual(dressing.ending_credits, video2) + + def test_dressing_to_json(self): + dressing = Dressing.objects.get(id=1) + dressing_json = dressing.to_json() + owner = User.objects.get(username="pod") + video = Video.objects.get(id=1) + video2 = Video.objects.get(id=2) + + expected_json = { + "id": dressing.id, + "title": "Test Dressing", + "allow_to_groups": [], + "owners": [owner.id], + "users": [owner.id], + "watermark": dressing.watermark.file.url, + "position": "En haut à droite", + "opacity": 50, + "opening_credits": video.slug, + "ending_credits": video2.slug, + } + self.assertEqual(dressing_json, expected_json) diff --git a/pod/dressing/tests/test_views.py b/pod/dressing/tests/test_views.py new file mode 100644 index 0000000000..46918e2294 --- /dev/null +++ b/pod/dressing/tests/test_views.py @@ -0,0 +1 @@ +"""Unit tests for dressing views.""" diff --git a/pod/dressing/tests/testimage.jpg b/pod/dressing/tests/testimage.jpg new file mode 100644 index 0000000000..933f8ab749 Binary files /dev/null and b/pod/dressing/tests/testimage.jpg differ diff --git a/pod/dressing/utils.py b/pod/dressing/utils.py index cdb8eb12ba..f89b15fd8b 100644 --- a/pod/dressing/utils.py +++ b/pod/dressing/utils.py @@ -4,6 +4,7 @@ def get_position_value(position, height): + """Obtain dimensions proportional to the video format.""" height = str(float(height) * 0.05) if position == 'top_right': return 'overlay=main_w-overlay_w-' + height + ':' + height @@ -16,6 +17,7 @@ def get_position_value(position, height): def get_dressing_input(dressing, FFMPEG_DRESSING_INPUT): + """Function to obtain the files necessary for encoding a dressed video""" command = '' if dressing.watermark: command += FFMPEG_DRESSING_INPUT % { diff --git a/pod/dressing/views.py b/pod/dressing/views.py index 81d630344b..4d72c8495a 100644 --- a/pod/dressing/views.py +++ b/pod/dressing/views.py @@ -57,6 +57,7 @@ def video_dressing(request, slug): @csrf_protect @login_required(redirect_field_name="referrer") def dressing_edit(request, dressing_id): + """Edit a dressing object.""" dressing_edit = get_object_or_404(Dressing, id=dressing_id) form_dressing = DressingForm( instance=dressing_edit, @@ -86,6 +87,7 @@ def dressing_edit(request, dressing_id): @csrf_protect @login_required(redirect_field_name="referrer") def dressing_create(request): + """Create a dressing object.""" if request.method == 'POST': form_dressing = DressingForm(request.POST, user=request.user) if form_dressing.is_valid(): @@ -129,7 +131,7 @@ def dressing_delete(request, dressing_id): @csrf_protect @login_required(redirect_field_name="referrer") def my_dressings(request): - """Render the logged user's dressing""" + """Render the logged user's dressings.""" if in_maintenance(): return redirect(reverse("maintenance")) user = request.user diff --git a/pod/video_encode_transcript/Encoding_video.py b/pod/video_encode_transcript/Encoding_video.py index 75b194cf9a..8cb0698d01 100644 --- a/pod/video_encode_transcript/Encoding_video.py +++ b/pod/video_encode_transcript/Encoding_video.py @@ -393,12 +393,14 @@ def get_hls_command(self): return hls_command def get_dressing_file(self): + """Create or replace the dressed video file.""" dirname = os.path.dirname(self.video_file) filename, ext = os.path.splitext(os.path.basename(self.video_file)) output_file = os.path.join(dirname, filename + "_dressing" + ext) return output_file def get_dressing_command(self): + """Get the command based on the dressing object parameters""" height = str(list(self.list_video_track.items())[0][1]["height"]) order_opening_credits = 0 dressing_command_params = '[vid][0:a]' @@ -462,6 +464,7 @@ def get_dressing_command(self): return dressing_command def encode_video_dressing(self): + """Encode the dressed video.""" dressing_command = self.get_dressing_command() return_value, return_msg = launch_cmd(dressing_command) self.add_encoding_log("dressing_command", dressing_command, return_value,