Skip to content

Commit

Permalink
Merge branch 'master' into bmtcril/pii_annotations
Browse files Browse the repository at this point in the history
  • Loading branch information
bmtcril authored Dec 4, 2024
2 parents 1536d2d + b154484 commit e2bddda
Show file tree
Hide file tree
Showing 10 changed files with 175 additions and 26 deletions.
34 changes: 34 additions & 0 deletions edxval/tests/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,13 @@
status="test",
)

VIDEO_DICT_SIMPSONS = dict(
client_video_id="TheSimpsons",
duration=100.00,
edx_video_id="simpson-id",
status="test",
)

TRANSCRIPT_DATA = {
"overwatch": """
1
Expand Down Expand Up @@ -452,3 +459,30 @@
preferred_languages=['ar', 'en'],
video_source_language='en',
)

VIDEO_TRANSCRIPT_SIMPSON_ES = dict(
video_id='simpson-id',
language_code='es',
transcript='edxval/tests/data/The_Flash.srt',
provider=TranscriptProviderType.CIELO24,
file_format=TranscriptFormat.SRT,
file_data=TRANSCRIPT_DATA['flash']
)

VIDEO_TRANSCRIPT_SIMPSON_KO = dict(
video_id='simpson-id',
language_code='ko',
transcript='edxval/tests/data/The_Flash.srt',
provider=TranscriptProviderType.CIELO24,
file_format=TranscriptFormat.SRT,
file_data=TRANSCRIPT_DATA['flash']
)

VIDEO_TRANSCRIPT_SIMPSON_RU = dict(
video_id='simpson-id',
language_code='ru',
transcript='edxval/tests/data/The_Flash.srt',
provider=TranscriptProviderType.CIELO24,
file_format=TranscriptFormat.SRT,
file_data=TRANSCRIPT_DATA['flash']
)
69 changes: 69 additions & 0 deletions edxval/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@

from ddt import data, ddt, unpack
from django.urls import reverse
from edx_rest_framework_extensions.permissions import IsStaff
from rest_framework import status
from rest_framework.permissions import IsAuthenticated

from edxval.models import CourseVideo, EncodedVideo, Profile, TranscriptProviderType, Video, VideoTranscript
from edxval.serializers import TranscriptSerializer
Expand Down Expand Up @@ -1152,3 +1154,70 @@ def test_successful_response(self):
mock_video_ids.assert_called_once_with(course_id)

self.assertEqual(response.status_code, status.HTTP_200_OK)


@ddt
class VideoTranscriptDeleteTest(APIAuthTestCase):
"""
Tests for transcript bulk deletion handler.
"""
def setUp(self):
"""
Tests setup.
"""
self.url = reverse('video-transcripts')
self.patcher = patch.object(IsAuthenticated, "has_permission", return_value=True)
self.patcher = patch.object(IsStaff, "has_permission", return_value=True)
self.patcher.start()

self.video_1 = Video.objects.create(**constants.VIDEO_DICT_SIMPSONS)
self.transcript_data_es = constants.VIDEO_TRANSCRIPT_SIMPSON_ES
self.transcript_data_ko = constants.VIDEO_TRANSCRIPT_SIMPSON_KO
self.transcript_data_ru = constants.VIDEO_TRANSCRIPT_SIMPSON_RU
super().setUp()

def tearDown(self):
self.patcher.stop()

def test_transcript_fail_authorized(self):
with patch.object(IsAuthenticated, "has_permission", return_value=False):
response = self.client.delete(self.url)
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

def test_transcript_delete_fail_no_staff(self):
with patch.object(IsStaff, "has_permission", return_value=False):
response = self.client.delete(self.url)
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

def test_transcript_delete_success(self):
VideoTranscript.objects.create(
video=self.video_1,
language_code=self.transcript_data_es['language_code'],
file_format=self.transcript_data_es['file_format'],
provider=self.transcript_data_es['provider'],
)
VideoTranscript.objects.create(
video=self.video_1,
language_code=self.transcript_data_ko['language_code'],
file_format=self.transcript_data_ko['file_format'],
provider=self.transcript_data_ko['provider'],
)
VideoTranscript.objects.create(
video=self.video_1,
language_code=self.transcript_data_ru['language_code'],
file_format=self.transcript_data_ru['file_format'],
provider=self.transcript_data_ru['provider'],
)

response1 = self.client.delete(f'{self.url}?video_id=simpson-id&language_code=es')
self.assertEqual(response1.status_code, status.HTTP_204_NO_CONTENT)

response2 = self.client.delete(f'{self.url}?video_id=simpson-id&language_code=ko')
self.assertEqual(response2.status_code, status.HTTP_204_NO_CONTENT)

response3 = self.client.delete(f'{self.url}?video_id=simpson-id&language_code=ru')
self.assertEqual(response3.status_code, status.HTTP_204_NO_CONTENT)

def test_transcript_delete_fail_bad_request(self):
response = self.client.delete(self.url)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
3 changes: 3 additions & 0 deletions edxval/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
path('videos/video-transcripts/create/', views.VideoTranscriptView.as_view(),
name='create-video-transcript'
),
path('videos/video-transcripts/', views.VideoTranscriptView.as_view(),
name='video-transcripts'
),
path('videos/video-images/update/', views.VideoImagesView.as_view(),
name='update-video-images'
),
Expand Down
49 changes: 46 additions & 3 deletions edxval/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,19 @@
from django.core.exceptions import ValidationError
from django.shortcuts import get_object_or_404
from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthentication
from edx_rest_framework_extensions.permissions import IsStaff
from rest_framework import generics, status
from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import DjangoModelPermissions
from rest_framework.permissions import DjangoModelPermissions, IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView

from edxval.api import create_or_update_video_transcript, get_transcript_details_for_course, get_video_ids_for_course
from edxval.api import (
create_or_update_video_transcript,
delete_video_transcript,
get_transcript_details_for_course,
get_video_ids_for_course,
)
from edxval.models import (
LIST_MAX_ITEMS,
CourseVideo,
Expand Down Expand Up @@ -119,7 +125,11 @@ class VideoTranscriptView(APIView):
"""
authentication_classes = (JwtAuthentication, SessionAuthentication)

# noinspection PyMethodMayBeStatic
def get_permissions(self):
if self.request.method == 'DELETE':
return [IsAuthenticated(), IsStaff()]
return []

def post(self, request):
"""
Creates a video transcript instance with the given information.
Expand Down Expand Up @@ -174,6 +184,39 @@ def post(self, request):

return response

def delete(self, request):
"""
Delete a video transcript instance with the given information.
Arguments:
request: A WSGI request.
"""
params = ('video_id', 'language_code')
missing = [param for param in params if param not in request.query_params]
if missing:
LOGGER.warning(
'[VAL] Required transcript params are missing. %s', ' and '.join(missing)
)
return Response(
status=status.HTTP_400_BAD_REQUEST,
data=dict(message='{missing} must be specified.'.format(missing=' and '.join(missing)))
)

video_id = request.query_params.get('video_id')
language_code = request.query_params.get('language_code')

try:
delete_video_transcript(video_id=video_id, language_code=language_code)
except Exception as e: # pylint: disable=broad-exception-caught
return Response(
status=status.HTTP_500_INTERNAL_SERVER_ERROR,
data={'message': str(e)}
)

return Response(
status=status.HTTP_204_NO_CONTENT,
)


class CourseTranscriptsDetailView(APIView):
"""
Expand Down
4 changes: 2 additions & 2 deletions requirements/ci.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ charset-normalizer==3.4.0
# via requests
colorama==0.4.6
# via tox
coverage[toml]==7.6.7
coverage[toml]==7.6.8
# via coveralls
coveralls==4.0.1
# via -r requirements/ci.in
Expand Down Expand Up @@ -46,5 +46,5 @@ tox==4.23.2
# via -r requirements/ci.in
urllib3==2.2.3
# via requests
virtualenv==20.27.1
virtualenv==20.28.0
# via tox
14 changes: 7 additions & 7 deletions requirements/dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,20 +44,20 @@ click==8.1.7
# uvicorn
click-log==0.4.0
# via edx-lint
code-annotations==1.8.2
code-annotations==2.0.0
# via
# edx-lint
# edx-toggles
colorama==0.4.6
# via tox
coverage[toml]==7.6.7
coverage[toml]==7.6.8
# via
# -r requirements/test.in
# coveralls
# pytest-cov
coveralls==4.0.1
# via -r requirements/ci.in
cryptography==43.0.3
cryptography==44.0.0
# via
# pyjwt
# secretstorage
Expand Down Expand Up @@ -183,7 +183,7 @@ more-itertools==10.5.0
# jaraco-functools
multidict==6.1.0
# via yarl
newrelic==10.3.0
newrelic==10.3.1
# via edx-django-utils
nh3==0.2.18
# via readme-renderer
Expand Down Expand Up @@ -220,7 +220,7 @@ pycodestyle==2.12.1
# via -r requirements/quality.in
pycparser==2.22
# via cffi
pydantic==2.10.1
pydantic==2.10.2
# via fastapi
pydantic-core==2.27.1
# via pydantic
Expand All @@ -231,7 +231,7 @@ pygments==2.18.0
# diff-cover
# readme-renderer
# rich
pyjwt[crypto]==2.10.0
pyjwt[crypto]==2.10.1
# via
# drf-jwt
# edx-drf-extensions
Expand Down Expand Up @@ -334,7 +334,7 @@ urllib3==2.2.3
# twine
uvicorn==0.32.1
# via pact-python
virtualenv==20.27.1
virtualenv==20.28.0
# via tox
yarl==1.18.0
# via pact-python
Expand Down
2 changes: 1 addition & 1 deletion requirements/pip-tools.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pyproject-hooks==1.2.0
# via
# build
# pip-tools
wheel==0.45.0
wheel==0.45.1
# via pip-tools

# The following packages are considered to be unsafe in a requirements file:
Expand Down
2 changes: 1 addition & 1 deletion requirements/pip.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#
# make upgrade
#
wheel==0.45.0
wheel==0.45.1
# via -r requirements/pip.in

# The following packages are considered to be unsafe in a requirements file:
Expand Down
12 changes: 6 additions & 6 deletions requirements/quality.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,15 @@ click==8.1.7
# uvicorn
click-log==0.4.0
# via edx-lint
code-annotations==1.8.2
code-annotations==2.0.0
# via
# edx-lint
# edx-toggles
coverage[toml]==7.6.7
coverage[toml]==7.6.8
# via
# -r requirements/test.in
# pytest-cov
cryptography==43.0.3
cryptography==44.0.0
# via
# pyjwt
# secretstorage
Expand Down Expand Up @@ -161,7 +161,7 @@ more-itertools==10.5.0
# jaraco-functools
multidict==6.1.0
# via yarl
newrelic==10.3.0
newrelic==10.3.1
# via edx-django-utils
nh3==0.2.18
# via readme-renderer
Expand Down Expand Up @@ -189,7 +189,7 @@ pycodestyle==2.12.1
# via -r requirements/quality.in
pycparser==2.22
# via cffi
pydantic==2.10.1
pydantic==2.10.2
# via fastapi
pydantic-core==2.27.1
# via pydantic
Expand All @@ -199,7 +199,7 @@ pygments==2.18.0
# via
# readme-renderer
# rich
pyjwt[crypto]==2.10.0
pyjwt[crypto]==2.10.1
# via
# drf-jwt
# edx-drf-extensions
Expand Down
12 changes: 6 additions & 6 deletions requirements/test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ click==8.1.7
# edx-django-utils
# pact-python
# uvicorn
code-annotations==1.8.2
code-annotations==2.0.0
# via edx-toggles
coverage[toml]==7.6.7
coverage[toml]==7.6.8
# via
# -r requirements/test.in
# pytest-cov
cryptography==43.0.3
cryptography==44.0.0
# via pyjwt
ddt==1.7.2
# via -r requirements/test.in
Expand Down Expand Up @@ -108,7 +108,7 @@ mock==5.1.0
# via -r requirements/test.in
multidict==6.1.0
# via yarl
newrelic==10.3.0
newrelic==10.3.1
# via edx-django-utils
packaging==24.2
# via pytest
Expand All @@ -128,11 +128,11 @@ psutil==6.1.0
# pact-python
pycparser==2.22
# via cffi
pydantic==2.10.1
pydantic==2.10.2
# via fastapi
pydantic-core==2.27.1
# via pydantic
pyjwt[crypto]==2.10.0
pyjwt[crypto]==2.10.1
# via
# drf-jwt
# edx-drf-extensions
Expand Down

0 comments on commit e2bddda

Please sign in to comment.