diff --git a/cms/envs/common.py b/cms/envs/common.py index 15e1c39d1951..a106e6f02008 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -977,10 +977,15 @@ from xmodule.modulestore.inheritance import InheritanceMixin from xmodule.x_module import XModuleMixin -# These are the Mixins that should be added to every XBlock. -# This should be moved into an XBlock Runtime/Application object -# once the responsibility of XBlock creation is moved out of modulestore - cpennington +# These are the Mixins that will be added to every Blocklike upon instantiation. +# DO NOT EXPAND THIS LIST!! We want it eventually to be EMPTY. Why? Because dynamically adding functions/behaviors to +# objects at runtime is confusing for both developers and static tooling (pylint/mypy). Instead... +# - to add special Blocklike behaviors just for your site: override `XBLOCK_EXTRA_MIXINS` with your own XBlockMixins. +# - to add new functionality to all Blocklikes: add it to the base Blocklike class in the core openedx/XBlock repo. XBLOCK_MIXINS = ( + # TODO: For each of these, either + # (a) merge their functionality into the base Blocklike class, or + # (b) refactor their functionality out of the Blocklike objects and into the edx-platform block runtimes. LmsBlockMixin, InheritanceMixin, XModuleMixin, @@ -988,6 +993,12 @@ AuthoringMixin, TaggedBlockMixin, ) + +# .. setting_name: XBLOCK_EXTRA_MIXINS +# .. setting_default: () +# .. setting_description: Custom mixins that will be dynamically added to every XBlock and XBlockAside instance. +# These can be classes or dotted-path references to classes. +# For example: `XBLOCK_EXTRA_MIXINS = ('my_custom_package.my_module.MyCustomMixin',)` XBLOCK_EXTRA_MIXINS = () # Paths to wrapper methods which should be applied to every XBlock's FieldData. diff --git a/lms/envs/common.py b/lms/envs/common.py index e41a9b131b95..0c372aa8a53b 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -67,10 +67,6 @@ from openedx.core.lib.derived import derived, derived_collection_entry from openedx.core.release import doc_version from lms.djangoapps.lms_xblock.mixin import LmsBlockMixin -try: - from skill_tagging.skill_tagging_mixin import SkillTaggingMixin -except ImportError: - SkillTaggingMixin = None ################################### FEATURES ################################### # .. setting_name: PLATFORM_NAME @@ -1631,12 +1627,26 @@ def _make_mako_template_dirs(settings): from xmodule.modulestore.inheritance import InheritanceMixin # lint-amnesty, pylint: disable=wrong-import-order, wrong-import-position from xmodule.x_module import XModuleMixin # lint-amnesty, pylint: disable=wrong-import-order, wrong-import-position -# These are the Mixins that should be added to every XBlock. -# This should be moved into an XBlock Runtime/Application object -# once the responsibility of XBlock creation is moved out of modulestore - cpennington -XBLOCK_MIXINS = (LmsBlockMixin, InheritanceMixin, XModuleMixin, EditInfoMixin) -if SkillTaggingMixin: - XBLOCK_MIXINS += (SkillTaggingMixin,) +# These are the Mixins that will be added to every Blocklike upon instantiation. +# DO NOT EXPAND THIS LIST!! We want it eventually to be EMPTY. Why? Because dynamically adding functions/behaviors to +# objects at runtime is confusing for both developers and static tooling (pylint/mypy). Instead... +# - to add special Blocklike behaviors just for your site: override `XBLOCK_EXTRA_MIXINS` with your own XBlockMixins. +# - to add new functionality to all Blocklikes: add it to the base Blocklike class in the core openedx/XBlock repo. +XBLOCK_MIXINS = ( + # TODO: For each of these, either + # (a) merge their functionality into the base Blocklike class, or + # (b) refactor their functionality out of the Blocklike objects and into the edx-platform block runtimes. + LmsBlockMixin, + InheritanceMixin, + XModuleMixin, + EditInfoMixin, +) + +# .. setting_name: XBLOCK_EXTRA_MIXINS +# .. setting_default: () +# .. setting_description: Custom mixins that will be dynamically added to every XBlock and XBlockAside instance. +# These can be classes or dotted-path references to classes. +# For example: `XBLOCK_EXTRA_MIXINS = ('my_custom_package.my_module.MyCustomMixin',)` XBLOCK_EXTRA_MIXINS = () # .. setting_name: XBLOCK_FIELD_DATA_WRAPPERS diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt index 19dea21e9ac0..c20c1aff744f 100644 --- a/requirements/edx/base.txt +++ b/requirements/edx/base.txt @@ -1208,7 +1208,7 @@ webob==1.8.7 # xblock wrapt==1.16.0 # via -r requirements/edx/paver.txt -xblock[django]==1.10.0 +xblock[django]==3.0.0 # via # -r requirements/edx/kernel.in # acid-xblock diff --git a/requirements/edx/development.txt b/requirements/edx/development.txt index 72267883cfe6..cde11f0ccd8c 100644 --- a/requirements/edx/development.txt +++ b/requirements/edx/development.txt @@ -2171,7 +2171,7 @@ wrapt==1.16.0 # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt # astroid -xblock[django]==1.10.0 +xblock[django]==3.0.0 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt diff --git a/requirements/edx/doc.txt b/requirements/edx/doc.txt index 5812455cf2e3..3020f97d6a81 100644 --- a/requirements/edx/doc.txt +++ b/requirements/edx/doc.txt @@ -1466,7 +1466,7 @@ webob==1.8.7 # xblock wrapt==1.16.0 # via -r requirements/edx/base.txt -xblock[django]==1.10.0 +xblock[django]==3.0.0 # via # -r requirements/edx/base.txt # acid-xblock diff --git a/requirements/edx/testing.txt b/requirements/edx/testing.txt index 5555717a0411..f03e69ab5e0c 100644 --- a/requirements/edx/testing.txt +++ b/requirements/edx/testing.txt @@ -1590,7 +1590,7 @@ wrapt==1.16.0 # via # -r requirements/edx/base.txt # astroid -xblock[django]==1.10.0 +xblock[django]==3.0.0 # via # -r requirements/edx/base.txt # acid-xblock diff --git a/xmodule/modulestore/tests/test_api.py b/xmodule/modulestore/tests/test_api.py index e42d3ded46c2..4e665c9eecbc 100644 --- a/xmodule/modulestore/tests/test_api.py +++ b/xmodule/modulestore/tests/test_api.py @@ -46,7 +46,7 @@ def test_get_xblock_root_module_name(): mixed_done_xblock = runtime.construct_xblock_from_class(DoneXBlock, Mock()) - assert mixed_done_xblock.__module__ == 'xblock.internal' # Mixed classes has a runtime generated module name. + assert mixed_done_xblock.__module__ == 'xblock.core' assert mixed_done_xblock.unmixed_class == DoneXBlock, 'The unmixed_class property retains the original property.' assert get_xblock_root_module_name(mixed_done_xblock) == 'done' diff --git a/xmodule/modulestore/tests/test_inheritance.py b/xmodule/modulestore/tests/test_inheritance.py index eb98cbc4f9f9..253a9f7abf23 100644 --- a/xmodule/modulestore/tests/test_inheritance.py +++ b/xmodule/modulestore/tests/test_inheritance.py @@ -15,7 +15,7 @@ from xmodule.modulestore.inheritance import InheritanceMixin -class TestXBlock: +class TestXBlock(XBlock): """ An empty Xblock, to be used, when creating a block with mixins. """ diff --git a/xmodule/tests/xml/factories.py b/xmodule/tests/xml/factories.py index 0c183ebd72a4..23a57898b6dc 100644 --- a/xmodule/tests/xml/factories.py +++ b/xmodule/tests/xml/factories.py @@ -9,7 +9,6 @@ from factory import Factory, Sequence, lazy_attribute, post_generation from fs.osfs import OSFS from lxml import etree -from xblock.mixins import HierarchyMixin from xmodule.modulestore.inheritance import InheritanceMixin from xmodule.x_module import XModuleMixin @@ -70,7 +69,7 @@ class Meta: model = XmlImportData filesystem = OSFS(mkdtemp()) - xblock_mixins = (InheritanceMixin, XModuleMixin, HierarchyMixin) + xblock_mixins = (InheritanceMixin, XModuleMixin) url_name = Sequence(str) attribs = {} policy = {}