openedx.core.djangoapps.waffle_utils package

Contents

openedx.core.djangoapps.waffle_utils package#

Submodules#

openedx.core.djangoapps.waffle_utils.forms module#

Defines a form for providing validation of waffle overrides.

class openedx.core.djangoapps.waffle_utils.forms.WaffleFlagCourseOverrideAdminForm(data=None, files=None, auto_id='id_%s', prefix=None, initial=None, error_class=<class 'django.forms.utils.ErrorList'>, label_suffix=None, empty_permitted=False, instance=None, use_required_attribute=None, renderer=None)#

Bases: ModelForm

Input form for course-level override of waffle flags, allowing us to verify data.

class Meta#

Bases: object

fields = '__all__'#
model#

alias of WaffleFlagCourseOverrideModel

base_fields = {'course_id': <django.forms.fields.CharField object>, 'enabled': <django.forms.fields.BooleanField object>, 'note': <django.forms.fields.CharField object>, 'override_choice': <django.forms.fields.TypedChoiceField object>, 'waffle_flag': <django.forms.fields.CharField object>}#
clean_course_id()#

Validate the course id

clean_waffle_flag()#

Validate the waffle flag is specified.

declared_fields = {}#
property media#

Return all media required to render the widgets on this form.

class openedx.core.djangoapps.waffle_utils.forms.WaffleFlagOrgOverrideAdminForm(data=None, files=None, auto_id='id_%s', prefix=None, initial=None, error_class=<class 'django.forms.utils.ErrorList'>, label_suffix=None, empty_permitted=False, instance=None, use_required_attribute=None, renderer=None)#

Bases: ModelForm

Input form for org-level override of waffle flags, allowing us to verify data.

class Meta#

Bases: object

fields = '__all__'#
model#

alias of WaffleFlagOrgOverrideModel

base_fields = {'enabled': <django.forms.fields.BooleanField object>, 'note': <django.forms.fields.CharField object>, 'org': <django.forms.fields.CharField object>, 'override_choice': <django.forms.fields.TypedChoiceField object>, 'waffle_flag': <django.forms.fields.CharField object>}#
clean_org()#

Validate the org.

clean_waffle_flag()#

Validate the waffle flag is specified.

declared_fields = {}#
property media#

Return all media required to render the widgets on this form.

openedx.core.djangoapps.waffle_utils.models module#

Models for configuring waffle utils.

class openedx.core.djangoapps.waffle_utils.models.WaffleFlagCourseOverrideModel(*args, **kwargs)#

Bases: ConfigurationModel

Used to force a waffle flag on or off for a course.

Prioritization: A course-level waffle flag overrides a relevant org-level waffle flag. An org-level waffle flag overrides any defaults.

So: Course level overrides (THIS MODEL) (highest priority) ->

Org level overrides -> Defaults (lowest priority)

ALL_CHOICES = Choices(('on', 'on', 'Force On'), ('off', 'off', 'Force Off'), ('unset', 'unset', 'unset'))#
exception DoesNotExist#

Bases: ObjectDoesNotExist

KEY_FIELDS = ('waffle_flag', 'course_id')#
exception MultipleObjectsReturned#

Bases: MultipleObjectsReturned

OVERRIDE_CHOICES = Choices(('on', 'on', 'Force On'), ('off', 'off', 'Force Off'))#
change_date#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

changed_by#

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

changed_by_id#
course_id#

DO NOT REUSE THIS CLASS. Provided for backwards compatibility only!

A placeholder class that provides a way to set the attribute on the model.

enabled#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

get_next_by_change_date(*, field=<django.db.models.fields.DateTimeField: change_date>, is_next=True, **kwargs)#
get_override_choice_display(*, field=<django.db.models.fields.CharField: override_choice>)#
get_previous_by_change_date(*, field=<django.db.models.fields.DateTimeField: change_date>, is_next=False, **kwargs)#
id#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

note#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

override_choice#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

classmethod override_value(waffle_flag, course_id)#

Returns whether the waffle flag was overridden (on or off) for the course, or is unset.

Parameters:
  • waffle_flag (String) – The name of the flag.

  • course_id (CourseKey) – The course id for which the flag may have been overridden.

If the current config is not set or disabled for this waffle flag and

course id, returns ALL_CHOICES.unset.

Otherwise, returns ALL_CHOICES.on or ALL_CHOICES.off as configured for

the override_choice.

waffle_flag#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

class openedx.core.djangoapps.waffle_utils.models.WaffleFlagOrgOverrideModel(*args, **kwargs)#

Bases: ConfigurationModel

Used to force a waffle flag on or off for an organization.

This class mostly mirrors WaffleFlagCourseOverrideModel.

Prioritization: A course-level waffle flag overrides a relevant org-level waffle flag. An org-level waffle flag overrides any defaults.

So: Course level overrides (highest priority) ->

Org level overrides (THIS MODEL) -> Defaults (lowest priority)

ALL_CHOICES = Choices(('on', 'on', 'Force On'), ('off', 'off', 'Force Off'), ('unset', 'unset', 'unset'))#
exception DoesNotExist#

Bases: ObjectDoesNotExist

KEY_FIELDS = ('waffle_flag', 'org')#
exception MultipleObjectsReturned#

Bases: MultipleObjectsReturned

OVERRIDE_CHOICES = Choices(('on', 'on', 'Force On'), ('off', 'off', 'Force Off'))#
change_date#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

changed_by#

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

changed_by_id#
enabled#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

get_next_by_change_date(*, field=<django.db.models.fields.DateTimeField: change_date>, is_next=True, **kwargs)#
get_override_choice_display(*, field=<django.db.models.fields.CharField: override_choice>)#
get_previous_by_change_date(*, field=<django.db.models.fields.DateTimeField: change_date>, is_next=False, **kwargs)#
id#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

note#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

org#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

override_choice#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

classmethod override_value(waffle_flag, org)#

Returns whether the waffle flag was overridden (on or off) for the org, or is unset.

Parameters:
  • waffle_flag (String) – The name of the flag.

  • org (String) – The org for which the flag may have been overridden.

If the current config is not set or disabled for this waffle flag and

org, returns ALL_CHOICES.unset.

Otherwise, returns ALL_CHOICES.on or ALL_CHOICES.off as configured for

the override_choice.

waffle_flag#

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

openedx.core.djangoapps.waffle_utils.urls module#

URL definitions for waffle utils.

openedx.core.djangoapps.waffle_utils.views module#

Views that we will use to view toggle state in edx-platform.

class openedx.core.djangoapps.waffle_utils.views.FlagOverride(*values)#

Bases: Enum

Enumerates the supported CourseWaffleFlag overrides.

COURSE = 'COURSE'#
ORG = 'ORG'#
class openedx.core.djangoapps.waffle_utils.views.OverrideToggleStateReport#

Bases: ToggleStateReport

Override some of the methods from ToggleStateReport to expose toggles from both the WaffleFlagCourseOverrideModel and WaffleFlagOrgOverrideModel objects.

add_waffle_flag_instances(flags_dict)#

Append objects from WaffleFlagCourseOverrideModel and WaffleFlagOrgOverrideModel.

get_waffle_flag_computed_status(flag)#

Produce correct “computed_status” values for WaffleFlagCourseOverrideModel or WaffleFlagOrgOverrideModel instances.

class openedx.core.djangoapps.waffle_utils.views.ToggleStateView(**kwargs)#

Bases: APIView

An endpoint for displaying the state of toggles in edx-platform.

get(request)#

Expose toggle state report dict as a view.

permission_classes = (<class 'edx_rest_framework_extensions.permissions.IsStaff'>,)#

Module contents#

Extra utilities for waffle: most classes are defined in edx_toggles.toggles (https://edx-toggles.readthedocs.io/), but we keep here some extra classes for usage within edx-platform. These classes cover course override use cases.

class openedx.core.djangoapps.waffle_utils.CourseWaffleFlag(name, module_name, log_prefix='')#

Bases: WaffleFlag

Represents a single waffle flag that can be forced on/off for a course.

This class should be used instead of WaffleFlag when in the context of a course. This class will also respect any org-level overrides, though course-level overrides will take precedence.

Uses a cached waffle namespace.

Usage:

SOME_COURSE_FLAG = CourseWaffleFlag(‘my_namespace.some_course_feature’, __name__, log_prefix=’’)

And then we can check this flag in code with:

SOME_COURSE_FLAG.is_enabled(course_key)

To configure a course-level override, go to Django Admin “waffle_utils” -> “Waffle flag course overrides”.

Waffle flag: Set this to the flag name (e.g. my_namespace.some_course_feature). Course id: Set this to the course id (e.g. course-v1:edx+100+Demo) Override choice: (Force on/Force off). “Force on” will enable the waffle flag for all users in a course,

overriding any behavior configured on the waffle flag itself. “Force off” will disable the waffle flag for all users in a course, overriding any behavior configured on the waffle flag itself. Requires “Enabled” (see below) to apply.

Enabled: Must be marked as “enabled” in order for the override to be applied. These settings can’t be

deleted, so instead, you need to add another disabled override entry to disable the override.

To configure an org-level override, go to Django Admin “waffle_utils” -> “Waffle flag org overrides”.

Waffle flag: Set this to the flag name (e.g. my_namespace.some_course_feature). Org name: Set this to the organization name (e.g. edx) Override choice: (Force on/Force off). “Force on” will enable the waffle flag for all users in an org’s courses,

overriding any behavior configured on the waffle flag itself. “Force off” will disable the waffle flag for all users in a org’s courses, overriding any behavior configured on the waffle flag itself. Requires “Enabled” (see below) to apply.

Enabled: Must be marked as “enabled” in order for the override to be applied. These settings can’t be

deleted, so instead, you need to add another disabled override entry to disable the override.

is_enabled(course_key=None)#

Returns whether or not the flag is enabled within the context of a given course.

Can also be given the key of any other learning context (like a content library), but it will act like a regular waffle flag in that case.

Parameters:

course_key (Optional[CourseKey]) – The course to check for override before checking waffle. If omitted, check whether the flag is enabled outside the context of any course.