diff --git a/xblocks_contrib/html/html.py b/xblocks_contrib/html/html.py index 282e6292..7d3c6301 100644 --- a/xblocks_contrib/html/html.py +++ b/xblocks_contrib/html/html.py @@ -322,7 +322,7 @@ def get_context(self): # the root /c4x/ url for assets. This allows client-side substitutions to occur. return { "module": self, - "editable_metadata_fields": self.editable_metadata_fields, # pylint: disable=no-member + "editable_metadata_fields": self.editable_metadata_fields, "data": self.data, "base_asset_url": self.get_base_url_path_for_course_assets(self.location.course_key), "enable_latex_compiler": self.use_latex_compiler, @@ -371,7 +371,7 @@ def bind_for_student(self, user_id, wrappers=None): if self.scope_ids.user_id is not None and user_id == self.scope_ids.user_id: if getattr(self.runtime, "position", None): # update the position of the tab - self.position = self.runtime.position # pylint: disable=attribute-defined-outside-init + self.position = self.runtime.position return # # If we are switching users mid-request, save the data from the old user. @@ -402,7 +402,7 @@ def bind_for_student(self, user_id, wrappers=None): wrapped_field_data = self.runtime.service(self, "field-data-unbound") for wrapper in wrappers: wrapped_field_data = wrapper(wrapped_field_data) - self._bound_field_data = wrapped_field_data # pylint: disable=attribute-defined-outside-init + self._bound_field_data = wrapped_field_data if getattr(self.runtime, "uses_deprecated_field_data", False): # This approach is deprecated but old mongo's CachingDescriptorSystem still requires it. # For Split mongo's CachingDescriptor system, don't set ._field_data this way. diff --git a/xblocks_contrib/video/content.py b/xblocks_contrib/video/content.py index 461e278e..a9f9fa0d 100644 --- a/xblocks_contrib/video/content.py +++ b/xblocks_contrib/video/content.py @@ -1,13 +1,24 @@ -""" Video Block Static Content, class copied from StaticContent class in edx-platform/xmodule/contentstore/content.py """ +""" +Video Block Static Content. + +Class copied from StaticContent class in edx-platform/xmodule/contentstore/content.py +""" from opaque_keys import InvalidKeyError from opaque_keys.edx.keys import AssetKey from opaque_keys.edx.locator import AssetLocator -class VideoBlockStaticContent: # lint-amnesty, pylint: disable=missing-class-docstring - def __init__(self, loc, name, content_type, data, last_modified_at=None, thumbnail_location=None, import_path=None, - length=None, locked=False, content_digest=None): + +class VideoBlockStaticContent: + """ + Represents static content associated with a video block (such as video files or related assets). + """ + def __init__( # pylint: disable=too-many-positional-arguments + self, loc, name, content_type, data, last_modified_at=None, + thumbnail_location=None, import_path=None, length=None, locked=False, content_digest=None + ): self.location = loc - self.name = name # a display string which can be edited, and thus not part of the location which needs to be fixed # lint-amnesty, pylint: disable=line-too-long + # a display string which can be edited, and thus not part of the location which needs to be fixed + self.name = name self.content_type = content_type self._data = data self.length = length @@ -20,7 +31,7 @@ def __init__(self, loc, name, content_type, data, last_modified_at=None, thumbna self.content_digest = content_digest @staticmethod - def compute_location(course_key, path, revision=None, is_thumbnail=False): # lint-amnesty, pylint: disable=unused-argument + def compute_location(course_key, path, revision=None, is_thumbnail=False): # pylint: disable=unused-argument """ Constructs a location object for static content. @@ -48,6 +59,7 @@ def get_location_from_path(path): if path.startswith('/') or path.endswith('/'): # try stripping off the leading slash and try again return AssetKey.from_string(path.strip('/')) + return None @staticmethod def serialize_asset_key_with_slash(asset_key): diff --git a/xblocks_contrib/video/mixin.py b/xblocks_contrib/video/mixin.py index b75b466e..db4bc789 100644 --- a/xblocks_contrib/video/mixin.py +++ b/xblocks_contrib/video/mixin.py @@ -5,9 +5,11 @@ from xblock.core import XBlockMixin from xblock.fields import Scope, String -# Make '_' a no-op so we can scrape strings. Using lambda instead of + +# Make '_' a no-op so we can scrape strings. Using dummy function instead of # `django.utils.translation.gettext_noop` because Django cannot be imported in this file -_ = lambda text: text +def _(text): + return text class LicenseMixin(XBlockMixin): diff --git a/xblocks_contrib/video/studio_metadata_mixin.py b/xblocks_contrib/video/studio_metadata_mixin.py index 1c3808c3..38fd9345 100644 --- a/xblocks_contrib/video/studio_metadata_mixin.py +++ b/xblocks_contrib/video/studio_metadata_mixin.py @@ -123,7 +123,7 @@ def editable_metadata_fields(self): editable_fields.pop('sub') languages = [{'label': label, 'code': lang} for lang, label in settings.ALL_LANGUAGES] - languages.sort(key=lambda l: l['label']) + languages.sort(key=lambda lang_item: lang_item['label']) editable_fields['transcripts']['custom'] = True editable_fields['transcripts']['languages'] = languages editable_fields['transcripts']['type'] = 'VideoTranslations' @@ -148,7 +148,9 @@ def editable_metadata_fields(self): if video_config_service: for sub_id in possible_sub_ids: try: - _, sub_id, _ = video_config_service.get_transcript(self, lang='en', output_format=TranscriptExtensions.TXT) + _, sub_id, _ = video_config_service.get_transcript( + self, lang='en', output_format=TranscriptExtensions.TXT + ) transcripts_info['transcripts'] = dict(transcripts_info['transcripts'], en=sub_id) break except TranscriptNotFoundError: diff --git a/xblocks_contrib/video/tests/__init__.py b/xblocks_contrib/video/tests/__init__.py new file mode 100644 index 00000000..6fa36e42 --- /dev/null +++ b/xblocks_contrib/video/tests/__init__.py @@ -0,0 +1,3 @@ +""" +Tests for the video xblock. +""" diff --git a/xblocks_contrib/video/tests/test_video.py b/xblocks_contrib/video/tests/test_video.py deleted file mode 100644 index 784b92f2..00000000 --- a/xblocks_contrib/video/tests/test_video.py +++ /dev/null @@ -1,26 +0,0 @@ -""" -Tests for VideoBlock -""" - -from django.test import TestCase -from xblock.fields import ScopeIds -from xblock.test.toy_runtime import ToyRuntime - -from xblocks_contrib import VideoBlock - - -class TestVideoBlock(TestCase): - """Tests for VideoBlock""" - - def test_my_student_view(self): - """Test the basic view loads.""" - scope_ids = ScopeIds("1", "2", "3", "4") - block = VideoBlock(ToyRuntime(), scope_ids=scope_ids) - frag = block.student_view() - as_dict = frag.to_dict() - content = as_dict["content"] - self.assertIn( - "VideoBlock: count is now", - content, - "XBlock did not render correct student view", - ) diff --git a/xblocks_contrib/video/validation.py b/xblocks_contrib/video/validation.py index 2496f54c..45388ace 100644 --- a/xblocks_contrib/video/validation.py +++ b/xblocks_contrib/video/validation.py @@ -15,7 +15,9 @@ class StudioValidationMessage(ValidationMessage): TYPES = [ValidationMessage.WARNING, ValidationMessage.ERROR, NOT_CONFIGURED] - def __init__(self, message_type, message_text, action_label=None, action_class=None, action_runtime_event=None): + def __init__( # pylint: disable=too-many-positional-arguments + self, message_type, message_text, action_label=None, action_class=None, action_runtime_event=None + ): """ Create a new message. diff --git a/xblocks_contrib/video/video.py b/xblocks_contrib/video/video.py index d1a21813..4bb79a80 100644 --- a/xblocks_contrib/video/video.py +++ b/xblocks_contrib/video/video.py @@ -1,12 +1,16 @@ -"""Video is ungraded Xmodule for support video content. +""" +Video is ungraded Xmodule for support video content. It's new improved video block, which support additional feature: -- Can play non-YouTube video sources via in-browser HTML5 video player. -- YouTube defaults to HTML5 mode from the start. -- Speed changes in both YouTube and non-YouTube videos happen via -in-browser HTML5 video method (when in HTML5 mode). -- Navigational subtitles can be disabled altogether via an attribute -in XML. -Examples of html5 videos for manual testing: + +* Can play non-YouTube video sources via in-browser HTML5 video player. +* YouTube defaults to HTML5 mode from the start. +* Speed changes in both YouTube and non-YouTube videos happen via + in-browser HTML5 video method (when in HTML5 mode). +* Navigational subtitles can be disabled altogether via an attribute + in XML. + +Examples of html5 videos for manual testing:: + https://s3.amazonaws.com/edx-course-videos/edx-intro/edX-FA12-cware-1_100.mp4 https://s3.amazonaws.com/edx-course-videos/edx-intro/edX-FA12-cware-1_100.webm https://s3.amazonaws.com/edx-course-videos/edx-intro/edX-FA12-cware-1_100.ogv @@ -92,10 +96,6 @@ log = logging.getLogger(__name__) loader = ResourceLoader(__name__) -# Make '_' a no-op so we can scrape strings. Using lambda instead of -# `django.utils.translation.ugettext_noop` because Django cannot be imported in this file -_ = lambda text: text - EXPORT_IMPORT_COURSE_DIR = 'course' EXPORT_IMPORT_STATIC_DIR = 'static' @@ -103,12 +103,13 @@ @XBlock.wants('settings', 'completion', 'request_cache', 'video_config') @XBlock.needs('i18n', 'user') class VideoBlock( - VideoFields, VideoTranscriptsMixin, VideoStudioViewHandlers, VideoStudentViewHandlers, - StudioEditableXBlockMixin, LegacyXmlMixin, XBlock, - AjaxHandlerMixin, StudioMetadataMixin, - LicenseMixin): + VideoFields, VideoTranscriptsMixin, VideoStudioViewHandlers, VideoStudentViewHandlers, + StudioEditableXBlockMixin, LegacyXmlMixin, XBlock, + AjaxHandlerMixin, StudioMetadataMixin, + LicenseMixin): """ - XML source example: + XML source example:: +