Skip to content
Snippets Groups Projects
Commit 78c15297 authored by Régis Behmo's avatar Régis Behmo
Browse files

refactor: migrate toggle state report to edx_toggles

The toggle state report could not be shared with other IDAs. Here we make use
of the newly available report from edx_toggles, and customize it to add data
from WaffleFlagCourseOverrideModel.
parent ae7d4994
No related branches found
No related tags found
No related merge requests found
...@@ -13,7 +13,6 @@ from waffle.testutils import override_flag ...@@ -13,7 +13,6 @@ from waffle.testutils import override_flag
from .. import ( from .. import (
CourseWaffleFlag, CourseWaffleFlag,
WaffleFlagNamespace,
WaffleSwitchNamespace, WaffleSwitchNamespace,
) )
from ..models import WaffleFlagCourseOverrideModel from ..models import WaffleFlagCourseOverrideModel
...@@ -33,8 +32,7 @@ class TestCourseWaffleFlag(TestCase): ...@@ -33,8 +32,7 @@ class TestCourseWaffleFlag(TestCase):
TEST_COURSE_KEY = CourseKey.from_string("edX/DemoX/Demo_Course") TEST_COURSE_KEY = CourseKey.from_string("edX/DemoX/Demo_Course")
TEST_COURSE_2_KEY = CourseKey.from_string("edX/DemoX/Demo_Course_2") TEST_COURSE_2_KEY = CourseKey.from_string("edX/DemoX/Demo_Course_2")
TEST_NAMESPACE = WaffleFlagNamespace(NAMESPACE_NAME) TEST_COURSE_FLAG = CourseWaffleFlag(NAMESPACE_NAME, FLAG_NAME, __name__)
TEST_COURSE_FLAG = CourseWaffleFlag(TEST_NAMESPACE, FLAG_NAME, __name__)
def setUp(self): def setUp(self):
super().setUp() super().setUp()
...@@ -83,7 +81,7 @@ class TestCourseWaffleFlag(TestCase): ...@@ -83,7 +81,7 @@ class TestCourseWaffleFlag(TestCase):
Test flag with undefined waffle flag. Test flag with undefined waffle flag.
""" """
test_course_flag = CourseWaffleFlag( test_course_flag = CourseWaffleFlag(
self.TEST_NAMESPACE, self.NAMESPACE_NAME,
self.FLAG_NAME, self.FLAG_NAME,
__name__, __name__,
) )
...@@ -109,7 +107,7 @@ class TestCourseWaffleFlag(TestCase): ...@@ -109,7 +107,7 @@ class TestCourseWaffleFlag(TestCase):
""" """
crum.set_current_request(None) crum.set_current_request(None)
test_course_flag = CourseWaffleFlag( test_course_flag = CourseWaffleFlag(
self.TEST_NAMESPACE, self.NAMESPACE_NAME,
self.FLAG_NAME, self.FLAG_NAME,
__name__, __name__,
) )
...@@ -121,7 +119,7 @@ class TestCourseWaffleFlag(TestCase): ...@@ -121,7 +119,7 @@ class TestCourseWaffleFlag(TestCase):
""" """
crum.set_current_request(None) crum.set_current_request(None)
test_course_flag = CourseWaffleFlag( test_course_flag = CourseWaffleFlag(
self.TEST_NAMESPACE, self.NAMESPACE_NAME,
self.FLAG_NAME, self.FLAG_NAME,
__name__, __name__,
) )
......
""" """
Tests for waffle utils views. Tests for waffle utils views.
""" """
from django.conf import settings
from django.test import TestCase from django.test import TestCase
from django.test.utils import override_settings
from edx_toggles.toggles import SettingDictToggle, SettingToggle
from edx_toggles.toggles.testutils import override_waffle_flag
from rest_framework.test import APIRequestFactory from rest_framework.test import APIRequestFactory
from waffle.testutils import override_switch
from common.djangoapps.student.tests.factories import UserFactory from common.djangoapps.student.tests.factories import UserFactory
...@@ -19,118 +14,36 @@ TEST_WAFFLE_FLAG_NAMESPACE = WaffleFlagNamespace("test") ...@@ -19,118 +14,36 @@ TEST_WAFFLE_FLAG_NAMESPACE = WaffleFlagNamespace("test")
TEST_WAFFLE_FLAG = WaffleFlag(TEST_WAFFLE_FLAG_NAMESPACE, "flag", __name__) TEST_WAFFLE_FLAG = WaffleFlag(TEST_WAFFLE_FLAG_NAMESPACE, "flag", __name__)
# TODO: Missing coverage for:
# - computed_status
class ToggleStateViewTests(TestCase): # lint-amnesty, pylint: disable=missing-class-docstring class ToggleStateViewTests(TestCase): # lint-amnesty, pylint: disable=missing-class-docstring
"""
Tests for the toggle state report view.
"""
def test_success_for_staff(self): def test_success_for_staff(self):
response = self._get_toggle_state_response() response = get_toggle_state_response()
assert response.status_code == 200 assert response.status_code == 200
assert response.data assert response.data
def test_failure_for_non_staff(self): def test_failure_for_non_staff(self):
response = self._get_toggle_state_response(is_staff=False) response = get_toggle_state_response(is_staff=False)
assert response.status_code == 403 assert response.status_code == 403
@override_waffle_flag(TEST_WAFFLE_FLAG, True)
def test_response_with_waffle_flag(self):
response = self._get_toggle_state_response()
assert 'waffle_flags' in response.data
assert response.data['waffle_flags']
waffle_names = [waffle["name"] for waffle in response.data['waffle_flags']]
assert 'test.flag' in waffle_names
@override_switch('test.switch', True)
def test_response_with_waffle_switch(self):
response = self._get_toggle_state_response()
assert 'waffle_switches' in response.data
assert response.data['waffle_switches']
waffle_names = [waffle["name"] for waffle in response.data['waffle_switches']]
assert 'test.switch' in waffle_names
def test_response_with_setting_toggle(self):
_toggle = SettingToggle("MYSETTING", default=False, module_name="module1")
with override_settings(MYSETTING=True):
response = self._get_toggle_state_response()
assert {'name': 'MYSETTING', 'is_active': True, 'module': 'module1', 'class': 'SettingToggle'}\
in response.data['django_settings']
def test_response_with_existing_setting_dict_toggle(self): def test_response_with_existing_setting_dict_toggle(self):
response = self._get_toggle_state_response() response = get_toggle_state_response()
assert {'name': "FEATURES['MILESTONES_APP']", 'is_active': True, assert {
'module': 'common.djangoapps.util.milestones_helpers', "name": "FEATURES['MILESTONES_APP']",
'class': 'SettingDictToggle'} in response.data['django_settings'] "is_active": True,
"module": "common.djangoapps.util.milestones_helpers",
def test_response_with_new_setting_dict_toggle(self): "class": "SettingDictToggle",
_toggle = SettingDictToggle( } in response.data["django_settings"]
"CUSTOM_FEATURES", "MYSETTING", default=False, module_name="module1"
)
with override_settings(CUSTOM_FEATURES={"MYSETTING": True}):
response = self._get_toggle_state_response()
setting_dict = {toggle["name"]: toggle for toggle in response.data["django_settings"]}
assert {'name': "CUSTOM_FEATURES['MYSETTING']", 'is_active': True, 'module': 'module1',
'class': 'SettingDictToggle'} == setting_dict["CUSTOM_FEATURES['MYSETTING']"]
def test_setting_overridden_by_setting_toggle(self):
_toggle2 = SettingToggle(
"MYSETTING2", module_name="module1"
)
_toggle3 = SettingDictToggle(
"MYDICT", "MYSETTING3", module_name="module1"
)
with override_settings(MYSETTING1=True, MYSETTING2=False, MYDICT={"MYSETTING3": False}):
# Need to pre-load settings, otherwise they are not picked up by the view
assert settings.MYSETTING1
response = self._get_toggle_state_response()
setting_dict = {toggle["name"]: toggle for toggle in response.data["django_settings"]}
# Check that Django settings for which a SettingToggle exists have both the correct is_active and class values
assert setting_dict['MYSETTING1']['is_active']
assert 'class' not in setting_dict['MYSETTING1']
assert not setting_dict['MYSETTING2']['is_active']
assert 'SettingToggle' == setting_dict['MYSETTING2']['class']
assert not setting_dict["MYDICT['MYSETTING3']"]['is_active']
assert 'SettingDictToggle' == setting_dict["MYDICT['MYSETTING3']"]['class']
def test_no_duplicate_setting_toggle(self):
_toggle1 = SettingToggle(
"MYSETTING1", module_name="module1"
)
_toggle2 = SettingDictToggle(
"MYDICT", "MYSETTING2", module_name="module1"
)
with override_settings(MYSETTING1=True, MYDICT={"MYSETTING2": False}):
response = self._get_toggle_state_response()
# Check there are no duplicate setting/toggle
response_toggles_1 = [toggle for toggle in response.data["django_settings"] if toggle["name"] == "MYSETTING1"]
response_toggles_2 = [
toggle for toggle in response.data["django_settings"] if toggle["name"] == "MYDICT['MYSETTING2']"
]
assert 1 == len(response_toggles_1)
assert 1 == len(response_toggles_2)
def test_code_owners_without_module_information(self):
# Create a waffle flag without any associated module_name
waffle_flag = WaffleFlag(TEST_WAFFLE_FLAG_NAMESPACE, "flag2", module_name=None)
response = self._get_toggle_state_response(is_staff=True)
result = [
flag for flag in response.data["waffle_flags"] if flag["name"] == waffle_flag.name
][0]
assert 'code_owner' not in result
def test_course_overrides(self): def test_course_overrides(self):
models.WaffleFlagCourseOverrideModel.objects.create(waffle_flag="my.flag", enabled=True) models.WaffleFlagCourseOverrideModel.objects.create(waffle_flag="my.flag", enabled=True)
course_overrides = {} course_overrides = {}
# pylint: disable=protected-access report = toggle_state_views.CourseOverrideToggleStateReport()
toggle_state_views._add_waffle_flag_course_override_state(course_overrides) report.add_waffle_flag_instances(course_overrides)
toggle_state_views._add_waffle_flag_computed_status(course_overrides) report.add_waffle_flag_computed_status(course_overrides)
assert 'my.flag' in course_overrides assert 'my.flag' in course_overrides
assert 'course_overrides' in course_overrides['my.flag'] assert 'course_overrides' in course_overrides['my.flag']
...@@ -139,11 +52,39 @@ class ToggleStateViewTests(TestCase): # lint-amnesty, pylint: disable=missing-c ...@@ -139,11 +52,39 @@ class ToggleStateViewTests(TestCase): # lint-amnesty, pylint: disable=missing-c
assert 'on' == course_overrides['my.flag']['course_overrides'][0]['force'] assert 'on' == course_overrides['my.flag']['course_overrides'][0]['force']
assert 'both' == course_overrides['my.flag']['computed_status'] assert 'both' == course_overrides['my.flag']['computed_status']
def _get_toggle_state_response(self, is_staff=True): # lint-amnesty, pylint: disable=missing-function-docstring def test_computed_status(self):
request = APIRequestFactory().get('/api/toggles/state/') models.WaffleFlagCourseOverrideModel.objects.create(
user = UserFactory() waffle_flag="my.overriddenflag1", enabled=True, course_id="org/course/id"
user.is_staff = is_staff )
request.user = user models.WaffleFlagCourseOverrideModel.objects.create(
view = toggle_state_views.ToggleStateView.as_view() waffle_flag="my.overriddenflag2", enabled=True
response = view(request) )
return response models.WaffleFlagCourseOverrideModel.objects.create(
waffle_flag="my.disabledflag1", enabled=False, course_id="org/course/id"
)
course_overrides = {}
report = toggle_state_views.CourseOverrideToggleStateReport()
report.add_waffle_flag_instances(course_overrides)
report.add_waffle_flag_computed_status(course_overrides)
assert "both" == course_overrides["my.overriddenflag1"]["computed_status"]
assert "org/course/id" == course_overrides["my.overriddenflag1"]["course_overrides"][0]["course_id"]
assert "on" == course_overrides["my.overriddenflag1"]["course_overrides"][0]["force"]
assert "both" == course_overrides["my.overriddenflag2"]["computed_status"]
assert "None" == course_overrides["my.overriddenflag2"]["course_overrides"][0]["course_id"]
assert "on" == course_overrides["my.overriddenflag2"]["course_overrides"][0]["force"]
assert "my.disabledflag1" not in course_overrides
def get_toggle_state_response(is_staff=True):
"""
Query the toggle state API endpoint.
"""
request = APIRequestFactory().get('/api/toggles/state/')
request.user = UserFactory(is_staff=is_staff)
view = toggle_state_views.ToggleStateView.as_view()
response = view(request)
return response
...@@ -3,277 +3,121 @@ Views that we will use to view toggle state in edx-platform. ...@@ -3,277 +3,121 @@ Views that we will use to view toggle state in edx-platform.
""" """
from collections import OrderedDict from collections import OrderedDict
from django.conf import settings
from edx_django_utils.monitoring import get_code_owner_from_module
from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthentication from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthentication
from edx_rest_framework_extensions.permissions import IsStaff from edx_rest_framework_extensions.permissions import IsStaff
from edx_toggles.toggles import SettingDictToggle, SettingToggle from edx_toggles.toggles.state import ToggleStateReport, get_or_create_toggle_response
from rest_framework import permissions, views from rest_framework import permissions, views
from rest_framework.authentication import SessionAuthentication from rest_framework.authentication import SessionAuthentication
from rest_framework.response import Response from rest_framework.response import Response
from waffle.models import Flag, Switch
from . import WaffleFlag, WaffleSwitch
from .models import WaffleFlagCourseOverrideModel from .models import WaffleFlagCourseOverrideModel
class ToggleStateView(views.APIView): class CourseOverrideToggleStateReport(ToggleStateReport):
"""
An endpoint for displaying the state of toggles in edx-platform.
"""
authentication_classes = (JwtAuthentication, SessionAuthentication,)
permission_classes = (permissions.IsAuthenticated, IsStaff,)
def get(self, request): # lint-amnesty, pylint: disable=missing-function-docstring
response = OrderedDict()
response['waffle_flags'] = _get_all_waffle_flags()
response['waffle_switches'] = _get_all_waffle_switches()
response['django_settings'] = _get_settings_state()
return Response(response)
def _get_all_waffle_switches():
""" """
Gets all waffle switches and their state. Override some of the methods from ToggleStateReport to expose toggles from WaffleFlagCourseOverrideModel objects.
""" """
switches_dict = {}
_add_waffle_switch_instances(switches_dict)
_add_waffle_switch_state(switches_dict)
_add_waffle_switch_computed_status(switches_dict)
switch_list = list(switches_dict.values())
switch_list.sort(key=lambda toggle: toggle['name'])
return switch_list
def add_waffle_flag_instances(self, flags_dict):
"""
Append objects from WaffleFlagCourseOverrideModel.
"""
super().add_waffle_flag_state(flags_dict)
_add_waffle_flag_course_override_state(flags_dict)
def _add_waffle_switch_instances(switches_dict): def get_waffle_flag_computed_status(self, flag):
""" """
Add details from waffle switch instances, like code_owner. Produce correct "computed_status" values for WaffleFlagCourseOverrideModel instances.
""" """
waffle_switch_instances = WaffleSwitch.get_instances() computed_status = super().get_waffle_flag_computed_status(flag)
for switch_instance in waffle_switch_instances: # check course overrides only if computed_status is not already 'both'
switch = _get_or_create_toggle_response(switches_dict, switch_instance.name) if computed_status != "both" and "course_overrides" in flag:
_add_toggle_instance_details(switch, switch_instance) has_force_on = any(
override["force"] == "on" for override in flag["course_overrides"]
)
has_force_off = any(
override["force"] == "off" for override in flag["course_overrides"]
)
if has_force_on and has_force_off:
computed_status = "both"
elif has_force_on:
computed_status = "on" if computed_status == "on" else "both"
elif has_force_off:
computed_status = "off" if computed_status == "off" else "both"
return computed_status
def _add_waffle_switch_state(switches_dict): class ToggleStateView(views.APIView):
""" """
Add waffle switch state from the waffle Switch model. An endpoint for displaying the state of toggles in edx-platform.
""" """
waffle_switches = Switch.objects.all()
for switch_data in waffle_switches:
switch = _get_or_create_toggle_response(switches_dict, switch_data.name)
switch['is_active'] = 'true' if switch_data.active else 'false'
if switch_data.note:
switch['note'] = switch_data.note
switch['created'] = str(switch_data.created)
switch['modified'] = str(switch_data.modified)
authentication_classes = (
JwtAuthentication,
SessionAuthentication,
)
permission_classes = (IsStaff,)
def _add_waffle_switch_computed_status(switch_dict): def get(self, request):
""" """
Add computed status to each waffle switch. Expose toggle state report dict as a view.
""" """
for switch in switch_dict.values(): report = CourseOverrideToggleStateReport().as_dict()
computed_status = 'off' _add_waffle_flag_course_override_state(report["waffle_flags"])
if 'is_active' in switch: return Response(report)
if switch['is_active'] == 'true':
computed_status = 'on'
else:
computed_status = 'off'
switch['computed_status'] = computed_status
def _get_all_waffle_flags():
"""
Gets all waffle flags and their state.
"""
flags_dict = {}
_add_waffle_flag_instances(flags_dict)
_add_waffle_flag_state(flags_dict)
_add_waffle_flag_course_override_state(flags_dict)
_add_waffle_flag_computed_status(flags_dict)
flag_list = list(flags_dict.values())
flag_list.sort(key=lambda toggle: toggle['name'])
return flag_list
def _add_waffle_flag_course_override_state(flags_dict):
def _add_waffle_flag_instances(flags_dict):
""" """
Add details from waffle flag instances, like code_owner. Add waffle flag course override state from the WaffleFlagCourseOverrideModel model.
""" """
waffle_flag_instances = WaffleFlag.get_instances()
for flag_instance in waffle_flag_instances:
flag = _get_or_create_toggle_response(flags_dict, flag_instance.name)
_add_toggle_instance_details(flag, flag_instance)
flag_course_overrides = _get_flag_course_overrides()
def _add_waffle_flag_state(flags_dict): for flag_name, course_overrides_dict in flag_course_overrides.items():
""" course_overrides = [
Add waffle flag state from the waffle Flag model. course_override
""" for course_override in course_overrides_dict.values()
waffle_flags = Flag.objects.all() if not course_override.get("disabled")
for flag_data in waffle_flags: ]
flag = _get_or_create_toggle_response(flags_dict, flag_data.name) if course_overrides:
if flag_data.everyone is True: flag = get_or_create_toggle_response(flags_dict, flag_name)
everyone = 'yes' flag["course_overrides"] = course_overrides
elif flag_data.everyone is False:
everyone = 'no'
else:
everyone = 'unknown'
flag['everyone'] = everyone
if flag_data.note:
flag['note'] = flag_data.note
flag['created'] = str(flag_data.created)
flag['modified'] = str(flag_data.modified)
def _add_waffle_flag_course_override_state(flags_dict): def _get_flag_course_overrides():
""" """
Add waffle flag course override state from the WaffleFlagCourseOverrideModel model. Return flag objects from WaffleFlagCourseOverrideModel instances.
""" """
# This dict is keyed by flag name, and contains dicts keyed by course_id, the contains # This dict is keyed by flag name, and contains dicts keyed by course_id, the contains
# the final dict of metadata for a single course override that will be returned. # the final dict of metadata for a single course override that will be returned.
flag_course_overrides = OrderedDict() flag_course_overrides = OrderedDict()
# Note: We can't just get enabled records, because if a historical record is enabled but # Note: We can't just get enabled records, because if a historical record is enabled but
# the current record is disabled, we would not know this. We get all records, and mark # the current record is disabled, we would not know this. We get all records, and mark
# some overrides as disabled, and then later filter the disabled records. # some overrides as disabled, and then later filter the disabled records.
course_overrides_data = WaffleFlagCourseOverrideModel.objects.all() course_overrides_data = WaffleFlagCourseOverrideModel.objects.all().order_by(
course_overrides_data = course_overrides_data.order_by('waffle_flag', 'course_id', '-change_date') "waffle_flag", "course_id", "-change_date"
)
for course_override_data in course_overrides_data: for course_override_data in course_overrides_data:
if course_override_data.enabled:
course_override_fields = {
"force": course_override_data.override_choice,
"modified": str(course_override_data.change_date),
}
else:
# The current record may be disabled, but later history might be enabled.
# We'll filter these disabled records below.
course_override_fields = {"disabled": True}
course_override_created_at = str(course_override_data.change_date)
flag_name = course_override_data.waffle_flag flag_name = course_override_data.waffle_flag
course_id = str(course_override_data.course_id) course_id = str(course_override_data.course_id)
if flag_name not in flag_course_overrides: course_override = flag_course_overrides.setdefault(
flag_course_overrides[flag_name] = OrderedDict() flag_name, OrderedDict()
course_overrides = flag_course_overrides[flag_name] ).setdefault(course_id, OrderedDict())
if course_id not in course_overrides:
course_overrides[course_id] = OrderedDict()
course_override = course_overrides[course_id]
# data is reverse ordered by date, so the first record is the current record # data is reverse ordered by date, so the first record is the current record
if 'course_id' not in course_override: if "course_id" not in course_override:
course_override['course_id'] = course_id course_override["course_id"] = course_id
if not course_override_data.enabled: course_override.update(course_override_fields)
# The current record may be disabled, but later history might be enabled.
# We'll filter these disabled records below.
course_override['disabled'] = True
else:
course_override['force'] = course_override_data.override_choice
course_override['modified'] = str(course_override_data.change_date)
# data is reverse ordered by date, so the last record is the oldest record # data is reverse ordered by date, so the last record is the oldest record
course_override['created'] = str(course_override_data.change_date) course_override["created"] = course_override_created_at
return flag_course_overrides
for flag_name, course_overrides_dict in flag_course_overrides.items():
course_overrides = [
course_override for course_override in course_overrides_dict.values()
if 'disabled' not in course_override
]
if course_overrides:
flag = _get_or_create_toggle_response(flags_dict, flag_name)
flag['course_overrides'] = course_overrides
def _add_waffle_flag_computed_status(flags_dict):
"""
Add computed status to each waffle flag.
"""
for flag in flags_dict.values():
computed_status = 'off'
if 'everyone' in flag:
if flag['everyone'] == 'yes':
computed_status = 'on'
elif flag['everyone'] == 'unknown':
computed_status = 'both'
# check course overrides only if computed_status is not already 'both'
if computed_status != 'both' and 'course_overrides' in flag:
has_force_on = any(override['force'] == 'on' for override in flag['course_overrides'])
has_force_off = any(override['force'] == 'off' for override in flag['course_overrides'])
if has_force_on and has_force_off:
computed_status = 'both'
elif has_force_on:
computed_status = 'on' if computed_status == 'on' else 'both'
elif has_force_off:
computed_status = 'off' if computed_status == 'off' else 'both'
flag['computed_status'] = computed_status
def _get_settings_state():
"""
Return a list of setting-based toggles: Django settings, SettingToggle and SettingDictToggle instances.
SettingToggle and SettingDictToggle override the settings with identical names (if any).
"""
settings_dict = {}
_add_settings(settings_dict)
_add_setting_toggles(settings_dict)
_add_setting_dict_toggles(settings_dict)
return sorted(settings_dict.values(), key=(lambda toggle: toggle['name']))
def _add_settings(settings_dict):
"""
Fill the `settings_dict`: will only include values that are set to true or false.
"""
for setting_name, setting_value in vars(settings).items():
if isinstance(setting_value, dict):
for dict_name, dict_value in setting_value.items():
if isinstance(dict_value, bool):
name = setting_dict_name(setting_name, dict_name)
toggle_response = _get_or_create_toggle_response(settings_dict, name)
toggle_response['is_active'] = dict_value
elif isinstance(setting_value, bool):
toggle_response = _get_or_create_toggle_response(settings_dict, setting_name)
toggle_response['is_active'] = setting_value
def _add_setting_toggles(settings_dict):
"""
Fill the `settings_dict` with values from the list of SettingToggle instances.
"""
for toggle in SettingToggle.get_instances():
toggle_response = _get_or_create_toggle_response(settings_dict, toggle.name)
toggle_response["is_active"] = toggle.is_enabled()
_add_toggle_instance_details(toggle_response, toggle)
def _add_toggle_instance_details(toggle, toggle_instance):
"""
Add details (class, module, code_owner) from a specific toggle instance.
"""
toggle['class'] = toggle_instance.__class__.__name__
toggle['module'] = toggle_instance.module_name
if toggle_instance.module_name:
code_owner = get_code_owner_from_module(toggle_instance.module_name)
if code_owner:
toggle['code_owner'] = code_owner
def _add_setting_dict_toggles(settings_dict):
"""
Fill the `settings_dict` with values from the list of SettingDictToggle instances.
"""
for toggle in SettingDictToggle.get_instances():
name = setting_dict_name(toggle.name, toggle.key)
toggle_response = _get_or_create_toggle_response(settings_dict, name)
toggle_response["is_active"] = toggle.is_enabled()
_add_toggle_instance_details(toggle_response, toggle)
def _get_or_create_toggle_response(toggles_dict, toggle_name):
"""
Gets or creates a toggle response dict and adds it to the toggles_dict.
Returns:
Either the pre-existing toggle response, or a new toggle dict with its name set.
"""
if toggle_name in toggles_dict:
return toggles_dict[toggle_name]
toggle = OrderedDict()
toggle['name'] = toggle_name
toggles_dict[toggle_name] = toggle
return toggle
def setting_dict_name(dict_name, key):
"""
Return the name associated to a `dict_name[key]` setting.
"""
return "{dict_name}['{key}']".format(dict_name=dict_name, key=key)
...@@ -113,7 +113,7 @@ edx-search==3.0.0 # via -r requirements/edx/base.in ...@@ -113,7 +113,7 @@ edx-search==3.0.0 # via -r requirements/edx/base.in
edx-sga==0.16.0 # via -r requirements/edx/base.in edx-sga==0.16.0 # via -r requirements/edx/base.in
edx-submissions==3.2.4 # via -r requirements/edx/base.in, ora2 edx-submissions==3.2.4 # via -r requirements/edx/base.in, ora2
edx-tincan-py35==1.0.0 # via edx-enterprise edx-tincan-py35==1.0.0 # via edx-enterprise
edx-toggles==4.0.0 # via -r requirements/edx/base.in, edx-ace, edx-completion, edx-event-routing-backends, edxval, ora2 edx-toggles==4.1.0 # via -r requirements/edx/base.in, edx-ace, edx-completion, edx-event-routing-backends, edxval, ora2
edx-user-state-client==1.3.0 # via -r requirements/edx/base.in edx-user-state-client==1.3.0 # via -r requirements/edx/base.in
edx-when==2.0.0 # via -r requirements/edx/base.in, edx-proctoring edx-when==2.0.0 # via -r requirements/edx/base.in, edx-proctoring
edxval==2.0.1 # via -r requirements/edx/base.in edxval==2.0.1 # via -r requirements/edx/base.in
......
...@@ -126,7 +126,7 @@ edx-sga==0.16.0 # via -r requirements/edx/testing.txt ...@@ -126,7 +126,7 @@ edx-sga==0.16.0 # via -r requirements/edx/testing.txt
edx-sphinx-theme==2.0.0 # via -r requirements/edx/development.in edx-sphinx-theme==2.0.0 # via -r requirements/edx/development.in
edx-submissions==3.2.4 # via -r requirements/edx/testing.txt, ora2 edx-submissions==3.2.4 # via -r requirements/edx/testing.txt, ora2
edx-tincan-py35==1.0.0 # via -r requirements/edx/testing.txt, edx-enterprise edx-tincan-py35==1.0.0 # via -r requirements/edx/testing.txt, edx-enterprise
edx-toggles==4.0.0 # via -r requirements/edx/testing.txt, edx-ace, edx-completion, edx-event-routing-backends, edxval, ora2 edx-toggles==4.1.0 # via -r requirements/edx/testing.txt, edx-ace, edx-completion, edx-event-routing-backends, edxval, ora2
edx-user-state-client==1.3.0 # via -r requirements/edx/testing.txt edx-user-state-client==1.3.0 # via -r requirements/edx/testing.txt
edx-when==2.0.0 # via -r requirements/edx/testing.txt, edx-proctoring edx-when==2.0.0 # via -r requirements/edx/testing.txt, edx-proctoring
edxval==2.0.1 # via -r requirements/edx/testing.txt edxval==2.0.1 # via -r requirements/edx/testing.txt
......
...@@ -122,7 +122,7 @@ edx-search==3.0.0 # via -r requirements/edx/base.txt ...@@ -122,7 +122,7 @@ edx-search==3.0.0 # via -r requirements/edx/base.txt
edx-sga==0.16.0 # via -r requirements/edx/base.txt edx-sga==0.16.0 # via -r requirements/edx/base.txt
edx-submissions==3.2.4 # via -r requirements/edx/base.txt, ora2 edx-submissions==3.2.4 # via -r requirements/edx/base.txt, ora2
edx-tincan-py35==1.0.0 # via -r requirements/edx/base.txt, edx-enterprise edx-tincan-py35==1.0.0 # via -r requirements/edx/base.txt, edx-enterprise
edx-toggles==4.0.0 # via -r requirements/edx/base.txt, edx-ace, edx-completion, edx-event-routing-backends, edxval, ora2 edx-toggles==4.1.0 # via -r requirements/edx/base.txt, edx-ace, edx-completion, edx-event-routing-backends, edxval, ora2
edx-user-state-client==1.3.0 # via -r requirements/edx/base.txt edx-user-state-client==1.3.0 # via -r requirements/edx/base.txt
edx-when==2.0.0 # via -r requirements/edx/base.txt, edx-proctoring edx-when==2.0.0 # via -r requirements/edx/base.txt, edx-proctoring
edxval==2.0.1 # via -r requirements/edx/base.txt edxval==2.0.1 # via -r requirements/edx/base.txt
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment