diff --git a/common/lib/xmodule/xmodule/split_test_module.py b/common/lib/xmodule/xmodule/split_test_module.py index 5855e3aeb2..8612d856be 100644 --- a/common/lib/xmodule/xmodule/split_test_module.py +++ b/common/lib/xmodule/xmodule/split_test_module.py @@ -5,6 +5,7 @@ Module for running content split tests import json import logging +import threading from functools import reduce from operator import itemgetter from uuid import uuid4 @@ -32,31 +33,41 @@ _ = lambda text: text DEFAULT_GROUP_NAME = _(u'Group ID {group_id}') -class SplitTestFields(object): - """Fields needed for split test module""" - has_children = True +class UserPartitionValues(threading.local): + """ + A thread-local storage for available user_partitions + """ + def __init__(self): + super().__init__() + self.values = [] - # All available user partitions (with value and display name). This is updated each time - # editable_metadata_fields is called. - user_partition_values = [] - # Default value used for user_partition_id - no_partition_selected = {'display_name': _("Not Selected"), 'value': -1} - - @staticmethod - def build_partition_values(all_user_partitions, selected_user_partition): + def build_partition_values(self, all_user_partitions, selected_user_partition): """ This helper method builds up the user_partition values that will be passed to the Studio editor """ - SplitTestFields.user_partition_values = [] + self.values = [] # Add "No selection" value if there is not a valid selected user partition. if not selected_user_partition: - SplitTestFields.user_partition_values.append(SplitTestFields.no_partition_selected) + self.values.append(SplitTestFields.no_partition_selected) for user_partition in get_split_user_partitions(all_user_partitions): - SplitTestFields.user_partition_values.append( + self.values.append( {"display_name": user_partition.name, "value": user_partition.id} ) - return SplitTestFields.user_partition_values + return self.values + + +# All available user partitions (with value and display name). This is updated each time +# editable_metadata_fields is called. +user_partition_values = UserPartitionValues() + + +class SplitTestFields(object): + """Fields needed for split test module""" + has_children = True + + # Default value used for user_partition_id + no_partition_selected = {'display_name': _("Not Selected"), 'value': -1} display_name = String( display_name=_("Display Name"), @@ -77,7 +88,7 @@ class SplitTestFields(object): scope=Scope.content, display_name=_("Group Configuration"), default=no_partition_selected["value"], - values=lambda: SplitTestFields.user_partition_values # Will be populated before the Studio editor is shown. + values=lambda: user_partition_values.values # Will be populated before the Studio editor is shown. ) # group_id is an int @@ -478,7 +489,7 @@ class SplitTestDescriptor(SplitTestFields, SequenceDescriptor, StudioEditableDes @property def editable_metadata_fields(self): # Update the list of partitions based on the currently available user_partitions. - SplitTestFields.build_partition_values(self.user_partitions, self.get_selected_partition()) + user_partition_values.build_partition_values(self.user_partitions, self.get_selected_partition()) editable_fields = super(SplitTestDescriptor, self).editable_metadata_fields diff --git a/common/lib/xmodule/xmodule/tests/test_split_test_module.py b/common/lib/xmodule/xmodule/tests/test_split_test_module.py index 4430877067..110c12ff32 100644 --- a/common/lib/xmodule/xmodule/tests/test_split_test_module.py +++ b/common/lib/xmodule/xmodule/tests/test_split_test_module.py @@ -11,7 +11,12 @@ from mock import Mock, patch from xmodule.partitions.partitions import MINIMUM_STATIC_PARTITION_ID, Group, UserPartition from xmodule.partitions.tests.test_partitions import MockPartitionService, MockUserPartitionScheme, PartitionTestCase -from xmodule.split_test_module import SplitTestDescriptor, SplitTestFields, get_split_user_partitions +from xmodule.split_test_module import ( + SplitTestDescriptor, + SplitTestFields, + get_split_user_partitions, + user_partition_values, +) from xmodule.tests import get_test_system from xmodule.tests.xml import XModuleXmlImportTest from xmodule.tests.xml import factories as xml @@ -276,12 +281,12 @@ class SplitTestModuleStudioTest(SplitTestModuleTest): """ Tests that the available partitions are populated correctly when editable_metadata_fields are called """ - self.assertEqual([], SplitTestDescriptor.user_partition_id.values) + self.assertEqual([], user_partition_values.values) # user_partitions is empty, only the "Not Selected" item will appear. self.split_test_module.user_partition_id = SplitTestFields.no_partition_selected['value'] self.split_test_module.editable_metadata_fields # pylint: disable=pointless-statement - partitions = SplitTestDescriptor.user_partition_id.values + partitions = user_partition_values.values self.assertEqual(1, len(partitions)) self.assertEqual(SplitTestFields.no_partition_selected['value'], partitions[0]['value']) @@ -298,7 +303,7 @@ class SplitTestModuleStudioTest(SplitTestModuleTest): ) ] self.split_test_module.editable_metadata_fields # pylint: disable=pointless-statement - partitions = SplitTestDescriptor.user_partition_id.values + partitions = user_partition_values.values self.assertEqual(2, len(partitions)) self.assertEqual(SplitTestFields.no_partition_selected['value'], partitions[0]['value']) self.assertEqual(0, partitions[1]['value']) @@ -307,7 +312,7 @@ class SplitTestModuleStudioTest(SplitTestModuleTest): # Try again with a selected partition and verify that there is no option for "No Selection" self.split_test_module.user_partition_id = 0 self.split_test_module.editable_metadata_fields # pylint: disable=pointless-statement - partitions = SplitTestDescriptor.user_partition_id.values + partitions = user_partition_values.values self.assertEqual(1, len(partitions)) self.assertEqual(0, partitions[0]['value']) self.assertEqual("first_partition", partitions[0]['display_name']) @@ -315,7 +320,7 @@ class SplitTestModuleStudioTest(SplitTestModuleTest): # Finally try again with an invalid selected partition and verify that "No Selection" is an option self.split_test_module.user_partition_id = 999 self.split_test_module.editable_metadata_fields # pylint: disable=pointless-statement - partitions = SplitTestDescriptor.user_partition_id.values + partitions = user_partition_values.values self.assertEqual(2, len(partitions)) self.assertEqual(SplitTestFields.no_partition_selected['value'], partitions[0]['value']) self.assertEqual(0, partitions[1]['value'])