From 46bbd0a668ac15471d4ca58e8d677f0bde3dc208 Mon Sep 17 00:00:00 2001 From: Sarina Canelake <sarina@edx.org> Date: Fri, 11 Dec 2015 14:54:45 -0500 Subject: [PATCH] Remove outdated abtest_module --- common/lib/xmodule/setup.py | 1 - common/lib/xmodule/xmodule/abtest_module.py | 159 -------------------- 2 files changed, 160 deletions(-) delete mode 100644 common/lib/xmodule/xmodule/abtest_module.py diff --git a/common/lib/xmodule/setup.py b/common/lib/xmodule/setup.py index 5b6b0b58f5a..1bc19588bd2 100644 --- a/common/lib/xmodule/setup.py +++ b/common/lib/xmodule/setup.py @@ -1,7 +1,6 @@ from setuptools import setup, find_packages XMODULES = [ - "abtest = xmodule.abtest_module:ABTestDescriptor", "book = xmodule.backcompat_module:TranslateCustomTagDescriptor", "chapter = xmodule.seq_module:SequenceDescriptor", "combinedopenended = xmodule.combined_open_ended_module:CombinedOpenEndedDescriptor", diff --git a/common/lib/xmodule/xmodule/abtest_module.py b/common/lib/xmodule/xmodule/abtest_module.py deleted file mode 100644 index a4b5ab48a67..00000000000 --- a/common/lib/xmodule/xmodule/abtest_module.py +++ /dev/null @@ -1,159 +0,0 @@ -import random -import logging -from lxml import etree - -from xmodule.x_module import XModule -from xmodule.raw_module import RawDescriptor -from xmodule.xml_module import XmlDescriptor -from xmodule.exceptions import InvalidDefinitionError -from xblock.fields import String, Scope, Dict - -DEFAULT = "_DEFAULT_GROUP" - - -log = logging.getLogger(__name__) - - -def group_from_value(groups, v): - """ - Given group: (('a', 0.3), ('b', 0.4), ('c', 0.3)) and random value v - in [0,1], return the associated group (in the above case, return - 'a' if v < 0.3, 'b' if 0.3 <= v < 0.7, and 'c' if v > 0.7 - """ - sum = 0 - for (g, p) in groups: - sum = sum + p - if sum > v: - return g - - # Round off errors might cause us to run to the end of the list. - # If the do, return the last element. - return g - - -class ABTestFields(object): - group_portions = Dict(help="What proportions of students should go in each group", default={DEFAULT: 1}, scope=Scope.content) - group_assignments = Dict(help="What group this user belongs to", scope=Scope.preferences, default={}) - group_content = Dict(help="What content to display to each group", scope=Scope.content, default={DEFAULT: []}) - experiment = String(help="Experiment that this A/B test belongs to", scope=Scope.content) - has_children = True - - -class ABTestModule(ABTestFields, XModule): - """ - Implements an A/B test with an aribtrary number of competing groups - """ - - def __init__(self, *args, **kwargs): - super(ABTestModule, self).__init__(*args, **kwargs) - - if self.group is None: - self.group = group_from_value( - self.group_portions.items(), - random.uniform(0, 1) - ) - - @property - def group(self): - return self.group_assignments.get(self.experiment) - - @group.setter - def group(self, value): - self.group_assignments[self.experiment] = value - - @group.deleter - def group(self): - del self.group_assignments[self.experiment] - - def get_child_descriptors(self): - active_locations = set(self.group_content[self.group]) - return [desc for desc in self.descriptor.get_children() if desc.location.to_deprecated_string() in active_locations] - - def displayable_items(self): - # Most modules return "self" as the displayable_item. We never display ourself - # (which is why we don't implement get_html). We only display our children. - return self.get_children() - - -# TODO (cpennington): Use Groups should be a first class object, rather than being -# managed by ABTests -class ABTestDescriptor(ABTestFields, RawDescriptor, XmlDescriptor): - module_class = ABTestModule - - show_in_read_only_mode = True - - @classmethod - def definition_from_xml(cls, xml_object, system): - """ - XML Format: - <abtest experiment="experiment_name"> - <group name="a" portion=".1"><contenta/></group> - <group name="b" portion=".2"><contentb/></group> - <default><contentdefault/></default> - </abtest> - """ - experiment = xml_object.get('experiment') - - if experiment is None: - raise InvalidDefinitionError( - "ABTests must specify an experiment. Not found in:\n{xml}" - .format(xml=etree.tostring(xml_object, pretty_print=True))) - - group_portions = {} - group_content = {} - children = [] - - for group in xml_object: - if group.tag == 'default': - name = DEFAULT - else: - name = group.get('name') - group_portions[name] = float(group.get('portion', 0)) - - child_content_urls = [] - for child in group: - try: - child_block = system.process_xml(etree.tostring(child)) - child_content_urls.append(child_block.scope_ids.usage_id) - except: - log.exception("Unable to load child when parsing ABTest. Continuing...") - continue - - group_content[name] = child_content_urls - children.extend(child_content_urls) - - default_portion = 1 - sum( - portion for (name, portion) in group_portions.items() - ) - - if default_portion < 0: - raise InvalidDefinitionError("ABTest portions must add up to less than or equal to 1") - - group_portions[DEFAULT] = default_portion - children.sort() - - return { - 'group_portions': group_portions, - 'group_content': group_content, - }, children - - def definition_to_xml(self, resource_fs): - xml_object = etree.Element('abtest') - xml_object.set('experiment', self.experiment) - for name, group in self.group_content.items(): - if name == DEFAULT: - group_elem = etree.SubElement(xml_object, 'default') - else: - group_elem = etree.SubElement(xml_object, 'group', attrib={ - 'portion': str(self.group_portions[name]), - 'name': name, - }) - - for child_loc in group: - child = self.system.load_item(child_loc) - self.runtime.add_block_as_child_node(child, group_elem) - - return xml_object - - def has_dynamic_children(self): - return True -- GitLab