From 09b68b5a1fbe0130c8e8e5678c71fee7541ad88e Mon Sep 17 00:00:00 2001 From: Muhammad Afaq Shuaib Date: Mon, 17 Feb 2025 14:04:24 +0500 Subject: [PATCH] feat: add util method in edx-val for listing transcript_languages for a course --- edxval/__init__.py | 2 +- edxval/api.py | 24 ++++++++++++++++++++++-- edxval/settings/base.py | 2 ++ edxval/tests/test_api.py | 12 ++++++++++++ requirements/base.in | 1 + requirements/ci.txt | 4 ++-- requirements/dev.txt | 18 +++++++++--------- requirements/quality.txt | 16 ++++++++-------- requirements/test.txt | 14 +++++++------- 9 files changed, 64 insertions(+), 29 deletions(-) diff --git a/edxval/__init__.py b/edxval/__init__.py index ce09e541..c2df3f36 100644 --- a/edxval/__init__.py +++ b/edxval/__init__.py @@ -2,4 +2,4 @@ init """ -__version__ = '2.9.0' +__version__ = '2.9.1' diff --git a/edxval/api.py b/edxval/api.py index 67399b48..a9a5827e 100644 --- a/edxval/api.py +++ b/edxval/api.py @@ -1,12 +1,11 @@ """ The internal API for VAL. """ - - import logging from enum import Enum from uuid import uuid4 +from django.conf import settings from django.core.exceptions import ObjectDoesNotExist, ValidationError from django.core.files.base import ContentFile from django.core.paginator import Paginator @@ -18,6 +17,7 @@ from lxml.etree import Element, SubElement from pysrt.srtexc import Error +import cachetools.func from edxval.config.waffle import OVERRIDE_EXISTING_IMPORTED_TRANSCRIPTS from edxval.exceptions import ( InvalidTranscriptFormat, @@ -733,6 +733,26 @@ def get_videos_for_course(course_id, sort_field=None, sort_dir=SortDirection.asc ) +@cachetools.func.ttl_cache(maxsize=None, ttl=settings.TRANSCRIPT_LANG_CACHE_TIMEOUT) +def get_transcript_languages(course_id, provider_type): + """ + Returns a list of languages for which transcripts are available for a course + + Args: + course_id (str): course id + provider_type (str): transcript provider type + + Returns: + (list): A list of language codes + """ + course_video_ids = CourseVideo.objects.filter(course_id=course_id, is_hidden=False).values_list('video__id') + transcript_languages = ( + VideoTranscript.objects.filter(video__id__in=course_video_ids, provider=provider_type) + .values_list("language_code", flat=True).distinct() + ) + return list(transcript_languages) + + def get_course_videos_qset(course_id): """ Get a QuerySet of CourseVideos for a given course. diff --git a/edxval/settings/base.py b/edxval/settings/base.py index 694dac39..71e41f60 100644 --- a/edxval/settings/base.py +++ b/edxval/settings/base.py @@ -193,3 +193,5 @@ } }, ] + +TRANSCRIPT_LANG_CACHE_TIMEOUT = 60 * 60 * 24 # 24 hours diff --git a/edxval/tests/test_api.py b/edxval/tests/test_api.py index f440d692..64cfe405 100644 --- a/edxval/tests/test_api.py +++ b/edxval/tests/test_api.py @@ -3189,6 +3189,18 @@ def test_get_transcript_details_for_course_no_course_videos(self): self.assertEqual(len(course_transcript), 0) + @data( + (TranscriptProviderType.THREE_PLAY_MEDIA, ['en']), + (TranscriptProviderType.CIELO24, ['fr']) + ) + @unpack + def test_get_transcript_languages_for_course(self, provider_type, expected_languages): + """ + Verify that `get_transcript_languages` api function works as expected. + """ + transcript_languages = api.get_transcript_languages(self.course_id1, provider_type) + self.assertEqual(transcript_languages, expected_languages) + @ddt class TranscriptPreferencesTest(TestCase): diff --git a/requirements/base.in b/requirements/base.in index 35c26310..d528de30 100644 --- a/requirements/base.in +++ b/requirements/base.in @@ -11,3 +11,4 @@ pillow # for reserved keywords linter edx-toggles>=2.0.0 lxml pysrt +cachetools diff --git a/requirements/ci.txt b/requirements/ci.txt index 1df2f217..05c157e3 100644 --- a/requirements/ci.txt +++ b/requirements/ci.txt @@ -14,7 +14,7 @@ charset-normalizer==3.4.1 # via requests colorama==0.4.6 # via tox -coverage[toml]==7.6.10 +coverage[toml]==7.6.12 # via coveralls coveralls==4.0.1 # via -r requirements/ci.in @@ -48,5 +48,5 @@ urllib3==2.2.3 # via # -c requirements/common_constraints.txt # requests -virtualenv==20.29.1 +virtualenv==20.29.2 # via tox diff --git a/requirements/dev.txt b/requirements/dev.txt index b60561fd..f95bb0a7 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -50,14 +50,14 @@ code-annotations==2.2.0 # edx-toggles colorama==0.4.6 # via tox -coverage[toml]==7.6.10 +coverage[toml]==7.6.12 # via # -r requirements/test.in # coveralls # pytest-cov coveralls==4.0.1 # via -r requirements/ci.in -cryptography==44.0.0 +cryptography==44.0.1 # via # pyjwt # secretstorage @@ -69,7 +69,7 @@ dill==0.3.9 # via pylint distlib==0.3.9 # via virtualenv -django==4.2.18 +django==4.2.19 # via # -c requirements/common_constraints.txt # -r requirements/base.in @@ -165,7 +165,7 @@ jinja2==3.1.5 # diff-cover keyring==25.6.0 # via twine -lxml==5.3.0 +lxml==5.3.1 # via -r requirements/base.in markdown-it-py==3.0.0 # via rich @@ -183,7 +183,7 @@ more-itertools==10.6.0 # jaraco-functools multidict==6.1.0 # via yarl -newrelic==10.5.0 +newrelic==10.6.0 # via edx-django-utils nh3==0.2.20 # via readme-renderer @@ -195,7 +195,7 @@ packaging==24.2 # twine pact-python==2.3.1 # via -r requirements/test.in -pbr==6.1.0 +pbr==6.1.1 # via stevedore pillow==11.1.0 # via -r requirements/base.in @@ -248,7 +248,7 @@ pylint-plugin-utils==0.8.2 # via # pylint-celery # pylint-django -pymongo==4.11 +pymongo==4.11.1 # via edx-opaque-keys pynacl==1.5.0 # via edx-django-utils @@ -262,7 +262,7 @@ pytest==8.3.4 # pytest-django pytest-cov==6.0.0 # via -r requirements/test.in -pytest-django==4.9.0 +pytest-django==4.10.0 # via -r requirements/test.in python-slugify==8.0.4 # via code-annotations @@ -336,7 +336,7 @@ urllib3==2.2.3 # twine uvicorn==0.34.0 # via pact-python -virtualenv==20.29.1 +virtualenv==20.29.2 # via tox yarl==1.18.3 # via pact-python diff --git a/requirements/quality.txt b/requirements/quality.txt index 17c3654c..0a446864 100644 --- a/requirements/quality.txt +++ b/requirements/quality.txt @@ -43,11 +43,11 @@ code-annotations==2.2.0 # via # edx-lint # edx-toggles -coverage[toml]==7.6.10 +coverage[toml]==7.6.12 # via # -r requirements/test.in # pytest-cov -cryptography==44.0.0 +cryptography==44.0.1 # via # pyjwt # secretstorage @@ -55,7 +55,7 @@ ddt==1.7.2 # via -r requirements/test.in dill==0.3.9 # via pylint -django==4.2.18 +django==4.2.19 # via # -c requirements/common_constraints.txt # -r requirements/base.in @@ -143,7 +143,7 @@ jinja2==3.1.5 # via code-annotations keyring==25.6.0 # via twine -lxml==5.3.0 +lxml==5.3.1 # via -r requirements/base.in markdown-it-py==3.0.0 # via rich @@ -161,7 +161,7 @@ more-itertools==10.6.0 # jaraco-functools multidict==6.1.0 # via yarl -newrelic==10.5.0 +newrelic==10.6.0 # via edx-django-utils nh3==0.2.20 # via readme-renderer @@ -171,7 +171,7 @@ packaging==24.2 # twine pact-python==2.3.1 # via -r requirements/test.in -pbr==6.1.0 +pbr==6.1.1 # via stevedore pillow==11.1.0 # via -r requirements/base.in @@ -217,7 +217,7 @@ pylint-plugin-utils==0.8.2 # via # pylint-celery # pylint-django -pymongo==4.11 +pymongo==4.11.1 # via edx-opaque-keys pynacl==1.5.0 # via edx-django-utils @@ -229,7 +229,7 @@ pytest==8.3.4 # pytest-django pytest-cov==6.0.0 # via -r requirements/test.in -pytest-django==4.9.0 +pytest-django==4.10.0 # via -r requirements/test.in python-slugify==8.0.4 # via code-annotations diff --git a/requirements/test.txt b/requirements/test.txt index fc083f5c..e605fecd 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -31,11 +31,11 @@ click==8.1.8 # uvicorn code-annotations==2.2.0 # via edx-toggles -coverage[toml]==7.6.10 +coverage[toml]==7.6.12 # via # -r requirements/test.in # pytest-cov -cryptography==44.0.0 +cryptography==44.0.1 # via pyjwt ddt==1.7.2 # via -r requirements/test.in @@ -100,7 +100,7 @@ iniconfig==2.0.0 # via pytest jinja2==3.1.5 # via code-annotations -lxml==5.3.0 +lxml==5.3.1 # via -r requirements/base.in markupsafe==3.0.2 # via jinja2 @@ -108,13 +108,13 @@ mock==5.1.0 # via -r requirements/test.in multidict==6.1.0 # via yarl -newrelic==10.5.0 +newrelic==10.6.0 # via edx-django-utils packaging==24.2 # via pytest pact-python==2.3.1 # via -r requirements/test.in -pbr==6.1.0 +pbr==6.1.1 # via stevedore pillow==11.1.0 # via -r requirements/base.in @@ -136,7 +136,7 @@ pyjwt[crypto]==2.10.1 # via # drf-jwt # edx-drf-extensions -pymongo==4.11 +pymongo==4.11.1 # via edx-opaque-keys pynacl==1.5.0 # via edx-django-utils @@ -148,7 +148,7 @@ pytest==8.3.4 # pytest-django pytest-cov==6.0.0 # via -r requirements/test.in -pytest-django==4.9.0 +pytest-django==4.10.0 # via -r requirements/test.in python-slugify==8.0.4 # via code-annotations